我从数据服务得到一个可观察的返回到 Web api,它返回一个数组并正确填充父组件中的数据表。我通过@Input 将用于填充数据表的数组传递给子组件。单击父组件上的一行时,我会显示一个使用表单编辑单行的模式。当点击模态框上的保存按钮时,行信息被发送到子组件,该子组件调用服务器并正确更新信息。服务器返回更新后的对象,然后将其拼接到@Input 数组中。数据表永远不会更新,尽管我可以看到模型数组的更改确实发生了,并且 Angular 使用 Augury 检测到了这些更改。我尝试使用 NgZone、NgOnChanges 和 setter/getter 来强制更新数组,但无济于事。我在另一个项目中有完全相同的代码,它按预期工作。我不确定我在这里缺少什么。
父模板
<h2>Website Aliases</h2>
<p-dataTable #dt [value]="websiteAliases" selectionMode="single" [(selection)]="selectedWebsiteAlias"
(onRowSelect)="onRowSelect($event);wad.setEditValue(selectedWebsiteAlias)"
[paginator]="true" [rows]="100"
[sortMode]="multiple">
<p-header>
Website Aliases
<div style="float:right;">
<button pButton type="button" (click)="wad.setCreateValue();" icon="fa-plus"></button>
<button pButton type="button" (click)="reloadDataTable();" icon="fa-refresh"></button>
</div>
</p-header>
<p-column field="aliasID" header="Alias ID" sortable="true"></p-column>
<p-column field="webID" header="Web ID" [filter]="true" filterMatchMode="contains"></p-column>
<p-column field="csHost" header="CsHost" [filter]="true" filterMatchMode="contains"></p-column>
</p-dataTable>
<website-alias-detail #wad [websiteAlias]="selectedWebsiteAlias" [websiteAliases]="websiteAliases"></website-alias-detail>
父组件
import { Observable } from 'rxjs/Rx';
import { DataTableModule, DialogModule } from 'primeng/primeng';
import { WebsiteAliasDetailComponent } from './websitealiasdetails.component';
@Component({
selector: 'website-alias',
templateUrl: 'websitealias.component.html'
})
export class WebsiteAliasComponent {
constructor(private dataService: DataService) { }
private websiteAliases: WebsiteAlias[];
private selectedWebsiteAlias: WebsiteAlias;
ngOnInit(): void {
this.dataService.get('websitealias').subscribe(apiObjects => this.websiteAliases = apiObjects);
}
onRowSelect(row): void {
this.selectedWebsiteAlias = this.websiteAliases.find(websiteAlias => websiteAlias.aliasID === row.data.aliasID);
}
createWebsiteAlias(): void {
this.selectedWebsiteAlias = null;
}
reloadDataTable(): void {
this.dataService.get('websitealias').subscribe(apiObjects => this.websiteAliases = apiObjects);
}
}
子模板
<p-dialog #dialog modal="true" header="Website Alias Details" [(visible)]="display">
<form #form [formGroup]="alias">
<div class="alert alert-danger" [hidden]="alias.controls.webID.valid || (alias.controls.webID.pristine && !submitted)">
Web ID is required and only accepts numbers
</div>
<div class="alert alert-danger" [hidden]="alias.controls.csHost.valid || (alias.controls.csHost.pristine && !submitted)">
CS Host is required
</div>
<div class="divTable">
<div class="divTableBody">
<div class="divTableRow" *ngIf="alias">
<div class="divTableCell"><label>Alias ID: </label></div>
<div class="divTableCell"><label><input placeholder="Alias ID" formControlName="aliasID" readonly="readonly" /></label></div>
</div>
<div class="divTableRow">
<div class="divTableCell"><label>Web ID: </label></div>
<div class="divTableCell"><input placeholder="Web ID" formControlName="webID" /></div>
</div>
<div class="divTableRow">
<div class="divTableCell"><label>CS Host: </label></div>
<div class="divTableCell"><input placeholder="CS Host" formControlName="csHost" /></div>
</div>
<div class="divTableRow">
<div class="divTableCell">
<button pButton type="submit" label="Save" (click)="saveWebsiteAlias(alias.value)" [disabled]="alias.invalid" class="ui-button ui-button-primary"></button>
<button pButton type="button" label="Close" (click)="hideDialog();" class="ui-button ui-button-secondary"></button>
<button *ngIf="websiteAlias" pButton type="submit" label="Delete" (click)="deleteWebsiteAlias(alias.value)" class="ui-button ui-button-danger"></button>
</div>
</div>
</div>
</div>
</form>
</p-dialog>
子组件
import { Component, Input, Output, OnInit, ViewEncapsulation } from '@angular/core';
import { DataService } from '../../services/data.service';
import { WebsiteAlias } from './WebsiteAlias';
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
@Component({
selector: 'website-alias-detail',
templateUrl: 'websitealiasdetails.component.html',
encapsulation: ViewEncapsulation.None,
})
export class WebsiteAliasDetailComponent implements OnInit {
@Input() websiteAliases: WebsiteAlias[];
@Input() websiteAlias: WebsiteAlias;
public alias: FormGroup;
private api = 'websitealias';
private display: boolean = false;
private isEdited: boolean = false;
constructor(private dataService: DataService, private formBuilder: FormBuilder) { }
ngOnInit(): void {
this.alias = this.formBuilder.group({
aliasID: [''],
webID: ['', [Validators.required, Validators.pattern('[0-9]*')]],
csHost: ['',Validators.required]
});
}
setEditValue(websiteAlias: WebsiteAlias)
{
this.alias.patchValue({ aliasID: websiteAlias.aliasID, webID: websiteAlias.webID, csHost: websiteAlias.csHost});
this.isEdited = true;
this.showDialog();
}
setCreateValue()
{
this.alias.patchValue({ aliasID: '', webID: '', csHost: '' });
this.isEdited = false;
this.websiteAlias = null;
this.showDialog();
}
showDialog(): void {
this.display = true;
}
hideDialog(): void {
this.display = false;
}
saveWebsiteAlias(savedAlias: WebsiteAlias): void {
if (!this.isEdited)
this.createWebsiteAlias(savedAlias);
else {
this.editWebsiteAlias(savedAlias);
}
this.hideDialog();
}
deleteWebsiteAlias(deletedAlias: WebsiteAlias): void {
var idToDelete = 0;
this.dataService.delete(this.api, deletedAlias.aliasID).subscribe(deletedId => idToDelete = deletedId);
let websiteAliasToRemove = this.websiteAliases.find(web => web.aliasID === idToDelete);
let index: number = this.websiteAliases.indexOf(websiteAliasToRemove);
this.websiteAliases.splice(index, 1);
this.hideDialog();
}
createWebsiteAlias(createdAlias: WebsiteAlias): void {
var newAlias = new WebsiteAlias(0, createdAlias.webID, createdAlias.csHost);
this.dataService.post(this.api, newAlias).subscribe(apiObject => newAlias.aliasID = apiObject.aliasID);
this.websiteAliases.push(newAlias);
this.websiteAlias = newAlias;
}
editWebsiteAlias(updatedAlias: WebsiteAlias): void {
var idToUpdate = 0;
var aliases = this.websiteAliases;
this.dataService.put(this.api, updatedAlias).subscribe(apiObject => this.websiteAlias = apiObject);
let websiteAliasToEdit = aliases.find(web => web.aliasID === updatedAlias.aliasID);
let index: number = aliases.indexOf(websiteAliasToEdit);
this.websiteAliases.splice(index, 1, updatedAlias);
}
}