我有两个模块,一个是查看项模块,另一个是添加项模块。
我有app.view.component.ts
,app.add.component.cs
,但现在如何使用[(ng-model)]
值作为全局值
这是add.component.html
<table style="width:100%;">
<tr height="25">
<td align="right" width="45%">
<div class="label-man">
<span>* Item ID</span>
</div>
</td>
<!-- <td><input type="text" style="width:300px" id="itemIDVal"></td> -->
<td>
<input type="text" style="width:300px" name="itemId" id="FstTex" [(ngModel)]=" itemId">
</td>
</tr>
<tr height="25">
<td align="right">
<div class="label-man">
<span>Item Description</span>
</div>
</td>
<td>
<input type="text" style="width:300px" id="itemDescriptionVal" [(ngModel)]=" itemDesc">
</td>
</tr>
<tr height="25">
<td align="right">
<div class="label-man">
<span>* Item Classification</span>
</div>
</td>
<td>
<input type="text" style="width:300px" id="classificationVal" [(ngModel)]=" Classification">
</td>
</tr>
<tr height="25">
<td align="right">
<div class="label-man">
<span>* Item Sub-Classification</span>
</div>
</td>
<td>
<input type="text" style="width:300px" id="subClassificationVal" [(ngModel)]=" subClassification" />
</td>
</tr>
<tr>
<td class="buttons">
<a href="#">
<span>Save</span>
</a>
</td>
<td></td>
</tr>
</table>
<table style="width:100%; table-layout: fixed;" class="newtbl">
<thead>
<tr height="25">
<th width="25%">Item ID</th>
<th width="25%">Item Description</th>
<th width="25%">Item classification</th>
<th>Item Sub-Classification</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{inputItem.itemId}}</td>
<td>{{inputItem.itemDesc}}</td>
<td>{{inputItem.Classification}}</td>
<td>{{inputItem.subClassification}}</td>
</tr>
</tbody>
</table>
这是
view.componet.html
<table style="width:100%;">
<thead>
<tr>
<td>
<input type="text" placeholder="Please Enter Item ID" [(ngModel)]="itemId" />
</td>
<td>
<input type="text" placeholder="Please Enter Item Description" [(ngModel)]="itemDesc" />
</td>
<td>
<input type="text" placeholder=" Please Enter Classification" [(ngModel)]="Classification" />
</td>
<td>
<input type="text" placeholder="Please Enter Sub-Class" [(ngModel)]="subClassification" />
</td>
</tr>
<tr height="25">
<th width="25%">Item ID</th>
<th width="25%">Item Description</th>
<th width="25%">Item Classification</th>
<th>Item Sub-Classification
<span class="buttons">
<a>
<span>Add Record</span>
</a>
</span>
</th>
</tr>
<tr>
<td>{{itemId}}</td>
<td>{{itemDesc}}</td>
<td>{{Classification}}</td>
<td>{{subClassification}}</td>
</tr>
</thead>
</table>
这种情况是当我在
add.component.html
中输入值时,这些值直接作为行追加到view.component.html
中。我是新来的角度。 最佳答案
最简单的方法是通过Services
。检查这个stackblitz
为了简单起见,我没有使用Subject
或BehaviorSubject
。
我有两个组件,我们称它们为InputComponent
和TableComponent
。
第一个保存输入,第二个显示数据。
我还创建了一个名为DataService
的服务。
它包含一个名为data
的数组和一个将新行推送到data
的方法
@Injectable()
export class DataService {
data: any[] = [];
push(row) {
this.data.push(row);
}
}
让我们看看
InputComponent
如您所见,我注入了
DataComponent
并创建了两个输入当用户单击
ngModel
时,我将此数据推入button
数组并清除输入。@Component({
selector: 'input-comp',
template: `
<div>Enter first column: <input [(ngModel)]="model.firstValue" /></div>
<div>Enter second column: <input [(ngModel)]="model.secondValue" /></div>
<button (click)="onBtnClick()">Click me</button>
`
})
export class InputComponent {
model = {};
constructor(private dataService: DataService) {}
onBtnClick() {
this.dataService.push(this.model);
this.model = {};
}
}
在
dataService.data
上,我向用户显示TableComponent
,如下所示dataService.data
@Component({
selector: 'table-comp',
templateUrl: './table.component.html'
})
export class TableComponent {
constructor(public dataService: DataService) {}
}
table.component.ts
<table border="1">
<tbody>
<tr *ngFor="let row of dataService.data">
<td>{{row.firstValue}}</td>
<td>{{row.secondValue}}</td>
</tr>
</tbody>
</table>
当存在
table.component.html
时,上述解决方案不起作用上面的stackblitz工作得很好,因为我没有改变
ChangeDetectionStrategy.OnPush
的changeDetection
。但是,如果将TableComponent
的changeDetection
设置为TableComponent
,您将看到它不起作用。Check it out这是因为,现在你告诉
ChangeDetectionStrategy.OnPush
只听事件,比如Angular
s中的任何变化(我们没有)、内部事件等等。如果你不知道Input
你应该读一下。它提供了很大的性能改进。无论如何,让我们重构
ChangeDetectionStrategy.OnPush
和service
s以支持component
。Our final code
首先,我重构
ChangeDetectionStrategy.OnPush
以获得DataService
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class DataService {
private data: any[] = [];
private dataSubject: BehaviorSubject<any[]> = new BehaviorSubject(this.data);
public readonly data$ = this.dataSubject.asObservable();
push(row) {
this.data.push(row);
this.dataSubject.next(this.data);
}
}
现在,我们不再向外界公开
BehaviourSubject
数组,而是公开一个名为data
的可观测对象。而且,当一个新项目通过时,我们会更新我们的内部data$
并通过data
发布它。这样,将触发一个事件并通知所有订阅者。让我们看看我们的
dataSubject.next
<table border="1">
<tbody>
<tr *ngFor="let row of dataService.data$ | async">
<td>{{row.firstValue}}</td>
<td>{{row.secondValue}}</td>
</tr>
</tbody>
</table>
唯一的区别是,我们不是直接访问
TableComponent
数组,而是访问data
observatable并通过dataService.data$
管道订阅它。现在,每个人都很快乐,一切都很好。不带RXJ
有一种方法不需要RxJs,但我认为如果有许多级别的组件的话,这会很麻烦。看看final code
我删除了负责在两个组件之间传递数据的
async
。相反,现在当输入新输入并单击按钮时,data.service
会发出一个事件。InputComponent
通过TableComponent
检索data
。@Input
@Component({
selector: 'input-comp',
template: `
<div>Enter first column: <input [(ngModel)]="model.firstValue" /></div>
<div>Enter second column: <input [(ngModel)]="model.secondValue" /></div>
<button (click)="onBtnClick()">Click me</button>
`
})
export class InputComponent {
model = {};
@Output() modelChange: EventEmitter<any> = new EventEmitter();
constructor() {}
onBtnClick() {
this.modelChange.emit(this.model);
this.model = {};
}
}
InputComponent
@Component({
selector: 'table-comp',
template:`
<table border="1">
<tbody>
<tr *ngFor="let row of data">
<td>{{row.firstValue}}</td>
<td>{{row.secondValue}}</td>
</tr>
</tbody>
</table>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class TableComponent {
@Input() data: any[];
}
TableComponent
@Component({
selector: 'my-app',
template: `
<input-comp (modelChange)="onModelChange($event)"></input-comp>
<table-comp [data]="data"></table-comp>
`,
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
data = [];
onModelChange(newModel) {
this.data = [...this.data, newModel];
}
}
正如你可能已经注意到的,我不做
AppComponent
。这是因为,当将新数据推送到现有数组时,其对象引用将不会更改。因此,角度变化检测不会触发this.data.push(newModel)
并更新表格。TableComponent
使用现有的this.data = [...this.data, newModel]
数组并将其扩展到data
并添加...
。这样,您总是创建一个新实例,并且更改检测将正常工作。