我有两个模块,一个是“查看项目”模块,另一个是“添加项目”模块。
我有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
中。我是Angular的新手。
答案 0 :(得分:1)
最简单的方法是通过Services
。选中此stackblitz
为简单起见,我没有使用Subject
或BehaviorSubject
。
我有两个组成部分,我们将它们称为InputComponent
和TableComponent
。
第一个保留输入,第二个显示数据。
我也创建了一个名为DataService
的服务。
它包含一个名为data
的数组和一种将新行推送到data
@Injectable()
export class DataService {
data: any[] = [];
push(row) {
this.data.push(row);
}
}
我们来看看InputComponent
如您所见,我注入了DataComponent
并使用ngModel
s创建了两个输入
当用户单击button
时,我会将这些数据推入dataService.data
数组中并清除输入。
@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 = {};
}
}
在TableComponent
上,我向用户显示dataService.data
如下
table.component.ts
@Component({
selector: 'table-comp',
templateUrl: './table.component.html'
})
export class TableComponent {
constructor(public dataService: DataService) {}
}
table.component.html
<table border="1">
<tbody>
<tr *ngFor="let row of dataService.data">
<td>{{row.firstValue}}</td>
<td>{{row.secondValue}}</td>
</tr>
</tbody>
</table>
存在ChangeDetectionStrategy.OnPush
时,以上解决方案无效
由于我没有更改changeDetection
中的TableComponent
,所以上面的堆叠闪耀效果很好。但是,如果将changeDetection
中的TableComponent
设置为ChangeDetectionStrategy.OnPush
,则会发现它不起作用。 Check it out
这是因为,现在您告诉Angular
仅听事件,例如Input
中的任何变化(我们没有任何变化),内部事件等。如果您没有了解ChangeDetectionStrategy.OnPush
,您应该阅读一下。它提供了很大的性能改进。
无论如何,让我们重构service
和component
来支持ChangeDetectionStrategy.OnPush
。
首先,我将DataService
重构为一个BehaviourSubject
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);
}
}
现在,我们没有向外界公开data
数组,而是公开了一个名为data$
的Observable。并且,当有新项目通过时,我们将更新内部data
并通过dataSubject.next
发布。这样,将触发事件并通知所有订户。
让我们看看我们的TableComponent
<table border="1">
<tbody>
<tr *ngFor="let row of dataService.data$ | async">
<td>{{row.firstValue}}</td>
<td>{{row.secondValue}}</td>
</tr>
</tbody>
</table>
唯一的区别是,我们直接访问data
并通过dataService.data$
管道对其进行订阅,而不是直接访问async
数组。现在,每个人都很高兴,一切都很好。
没有RxJ
有一种没有RxJ的方法,但是我认为如果组件的级别很多,这将很麻烦。看看final code
我删除了data.service
,后者负责两个组件之间的数据传递。相反,现在InputComponent
会在输入新输入并单击按钮时发出事件。
TableComponent
通过data
检索@Input
。
InputComponent
@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 = {};
}
}
TableComponent
@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[];
}
AppComponent
@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];
}
}
您可能已经注意到,我没有this.data.push(newModel)
。这是因为,当您将新数据推送到现有数组时,其对象引用不会更改。因此,角度变化检测将不会为TableComponent
触发并更新表格。
this.data = [...this.data, newModel]
获取现有的data
数组,并与...
进行扩展,然后添加newModel
。这样,您总是可以创建一个新实例,更改检测就可以正常工作。