Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular6: Input binding on custom component doesn't update correctly

First question ever on StackOverflow, how exciting!

Currently I have two custom components, both accepting a couple of input variables :

<sod-matrix-table #matrix 
  [entities]="entities" 
  [pairs]="pairs" 
  [displayedColumns]="displayedColumns">
</sod-matrix-table>

and :

<data-table 
  #table 
  [type]="sodMatrixQuery.targetType" 
  [query]="sodMatrixQuery" >
</data-table>

When updating the entities, pairs or columns of the first tag, everything updates correctly. For example, when I update the displayedColumns array in a component that uses the matrix table tag, the table inside of that component gets updated with the desired columns.
However, when I update the sodMatrixQuery in the component, and press the search button, the query object of the data-table isn't updated correctly, although they are bound together.

Example:

data-table has a field query and uses this query to send REST requests to the server. SODMatrixComponent has a field sodMatrixQuery and uses the tag of the data-table, binding his field to the other field.

An SOD Matrix contains pairs of objects. When I select 2 pairs, and press the search button, the data-table sends the REST request with 2 pairs. However, when I remove the two pairs, and press search again, the data-table component sends another REST request, again with 2 pairs instead of none. When pressing the search button a second time, the correct request is send.

I debugged and internally everything with the pairs goes fine, it's only the databinding that doesn't get updated in time. Any thoughts about this?

EDIT: This is the code that happens on the button click:

public search() {
    const tempQuery = new SODMatrixQuery(this.lhsType, this.rhsType, [], this.entities);

    // Only look at elements above the diagonal
    for (let i = 1; i < this.pairs.length; i++) {
        for (let j = 0; j < i; j++ ) {
            const p = this.pairs[i][j];
            if (p.checked) {
                tempQuery.addToxicPair(p);
            }
        }
    }

    if (this.dataTable) {
        this.sodMatrixQuery = tempQuery;
        // this.dataTable.query = tempQuery;
        this.dataTable.loadDataPage();
    }

}

SODMatrixComponent variables :

@ViewChild("table")
public dataTable: ElimityDataTableComponent;

public sodMatrixQuery: SODMatrixQuery;

Datatable component :

@Input()
public query: Query;

SODMatrixQuery extends Query!

The commented line below is a fix, to update the query object directly, but I'm just curious why the databinding doesn't work.

like image 274
Bertijn Pauwels Avatar asked Sep 08 '26 20:09

Bertijn Pauwels


1 Answers

Looks like change detection would need a moment to breathe there - the databinding can't be updated between the setting of the sodMatrixQuery member and the this.dataTable.loadDataPage() call - that's why it still has the old value on the first call. After that change detection will be run and on the second call it will have the right values.

if (this.dataTable) {
    this.sodMatrixQuery = tempQuery;
    // can't update the bindings here
    this.dataTable.loadDataPage();
}

So looking at your current architecture, it would be better to move the loadDataPage() call to the dataTable component into the OnChanges lifecycle hook, like Agash said in the comments.

export class ElimityDataTableComponent implements OnChanges {
  // ...
  ngOnChanges(changes: SimpleChanges) {
    if (changes.query) {
      this.loadDataPage();
    }
  }

This way, every time you update the sodMatrixQuery, it automatically loads the new data.

like image 134
rinukkusu Avatar answered Sep 14 '26 07:09

rinukkusu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!