2017-05-05 1 views
4

Je reçois un retour observable d'un service de données vers une API Web qui renvoie un tableau et remplit correctement une table de données dans un composant parent. Je passe le tableau utilisé pour remplir la datatable à un composant enfant via @Input. Quand une ligne sur le composant parent est cliquée, je montre un modal pour éditer une seule ligne en utilisant un formulaire. Lorsque le bouton Enregistrer est cliqué sur le modal, les informations de ligne sont envoyées au composant enfant qui appelle le serveur et met à jour les informations correctement. Le serveur renvoie l'objet mis à jour qui est ensuite épissé dans le tableau @Input. La datatable ne se met jamais à jour bien que je puisse voir que les modifications apportées au tableau modèle se produisent et sont détectées par Angular en utilisant Augury. J'ai essayé d'utiliser NgZone, NgOnChanges et setters/getters pour que le tableau soit forcé de mettre à jour, en vain. J'ai exactement le même code dans un autre projet, et cela fonctionne comme prévu. Je ne suis pas sûr de ce qui me manque ici.Angular4 PrimeNG DataTable ne pas mettre à jour malgré les modifications du modèle

Parent Modèle

<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> 

Parent Composant

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

Template enfant

<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> 

Composante enfants

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

pouvez-vous créer un plunker de travail? – Aravind

Répondre

2

Regardez la réponse donnée dans [How to programmaticaly trigger refresh primeNG datatable when a button is clicked question: 1

Je n'ai pas assez représentant d'ajouter cela comme un commentaire, mais la réponse consiste à créer une variable « visible » avec * ngIf pour déclencher la recréation du DOm.

+0

ouais je viens d'opter pour un rafraîchissement des données sans reconstruire le dom - le cas d'utilisation était que d'autres utilisateurs puissent apporter des modifications, nous voulions donc nous assurer de capturer tous les changements et pas seulement ceux du navigateur de l'utilisateur. – xyntiacat