2017-05-05 48 views
4

我从数据服务得到一个可观察的返回到Web API,返回一个数组并正确地填充父组件中的数据表。我通过@Input将用于填充数据表的数组传递给子组件。当单击父组件上的一行时,我将显示一个使用Form编辑单行的模式。当在模式上单击保存按钮时,行信息被发送到调用服务器并正确更新信息的子组件。服务器返回更新的对象,然后将其拼接到@Input数组中。尽管我可以看到对模型数组的更改确实发生并且使用Augury检测到了Angular,但数据表从未更新。我尝试过使用NgZone,NgOnChanges和setter/getters来强制更新数组,但无济于事。我在另一个项目中使用完全相同的代码,并且它按预期工作。我不确定我在这里错过了什么。Angular4 PrimeNG DataTable不更新,尽管模型更改

父模板

<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); 
    } 

} 
+0

你可以创建一个工作plunker? – Aravind

回答

2

中只看[How to programmaticaly trigger refresh primeNG datatable when a button is clicked问题给出了答案:1

我没有足够的代表加入这个作为注释,但答案需要创建一个“看得见”的变化用* ngIf触发重新创建DOm。

+0

是的,我只是选择刷新数据而不重建dom--用例是我们可能会有其他用户进行更改,因此我们希望确保捕获所有更改,而不仅仅是用户浏览器中的更改。 – xyntiacat