Tuesday, 10 July 2018

Angular6: view not updating on data change despite binding

I made a custom component out of Angular material table. It is basically a recursive table that shows a subtable when clicking on a row, and a subsubtable when clicking on a row of the later. It required a recursive template. The table input data is quite large and takes the form of a JSON with arrays of JSON, etc... This format was decided by the rest of the project and is inflexible.
The data is stored in a variable called data. My table has input field to modify entries in data and I checked that it does work properly, my issue is that if updating data from outside the table, the table view does not change, there is not update. I am surprised by that as use binding when passing data to the component. I am beginner at Angular and not comfortable with Subjects and Observables yet, so I have not looked in that direction.
Here is the code.
For the recursive component:
@Component({
  selector: 'app-rectable',
  template: `
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

<div class="example-container mat-elevation-z8">
  <mat-table [dataSource]="theData">


    <ng-container matColumnDef="name">
      <mat-header-cell *matHeaderCellDef> channel </mat-header-cell>
      <mat-cell *matCellDef="let element">
        <button *ngIf="element.isexpandable" mat-icon-button
 (click)="element.isexpanded = !element.isexpanded;">
          <mat-icon class="mat-icon-rtl-mirror">
            
          </mat-icon>
        </button>
        <mat-form-field class="example-full-width">
          <input matInput [(ngModel)]="element.name" (input)="update($event)">
        </mat-form-field>
      </mat-cell>
    </ng-container>

    <ng-container matColumnDef="min">
      <mat-header-cell *matHeaderCellDef> min </mat-header-cell>
      <mat-cell *matCellDef="let element">
        <input matInput type=number [(ngModel)]="element.min" (input)="update($event)">
      </mat-cell>
    </ng-container>

    <ng-container matColumnDef="max">
      <mat-header-cell *matHeaderCellDef> max </mat-header-cell>
      <mat-cell *matCellDef="let element">
        <input matInput type=number [(ngModel)]="element.max" (input)="update($event)">
      </mat-cell>
    </ng-container>

    <ng-container matColumnDef="value">
      <mat-header-cell *matHeaderCellDef> value </mat-header-cell>
      <mat-cell *matCellDef="let element">
        
      </mat-cell>
    </ng-container>

    <ng-container matColumnDef="expandedDetail">
      <mat-cell *matCellDef="let detail">
        <app-rectable *ngIf="detail.element.isexpandable" [array]="detail.element.variables" 
[isTop]="false">
        </app-rectable>

      </mat-cell>
    </ng-container>

    <div *ngIf="isTop">
    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    </div>
    <mat-row *matRowDef="let row; columns: displayedColumns;" matRipple 
class="element-row" [class.expanded]="row.isexpanded" >
    </mat-row>
    <mat-row *matRowDef="let row; columns: ['expandedDetail']; when: 
isExpansionDetailRow" [@detailExpand]="row.element.isexpanded ? 'expanded' : 
'collapsed'" style="overflow: hidden">
    </mat-row>
  </mat-table>
</div>
<div *ngIf="!theData.value.length" > EMPTY DATA INPUT </div>
  `,
  styleUrls: ['./rectable.component.css'],
  animations: [
    trigger('detailExpand', [
      state('collapsed', style({ height: '0px', minHeight: '0', visibility: 'hidden' })),
      state('expanded', style({ height: '*', visibility: 'visible' })),
      transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
    ]),
  ],
})

export class RectableComponent implements OnInit {

  @Input() array;

  @Input() isTop: boolean;
  theData = [];
  displayedColumns = ["name", "min", "max", "value"];
  isExpansionDetailRow = (i: number, row: Object) => row.hasOwnProperty('detailRow');

  constructor() {
  }

  ngOnInit() {
    this.theData = observableOf(this.array);
  }

}

The root component html is
<app-rectable [array]='data' [isTop]="true"></app-rectable>

Where data is a JSON object, which I prefer not to explicit here.


from Angular6: view not updating on data change despite binding

No comments:

Post a Comment