Ngx-datatable: Re-ordering rows does not cause view to update

Created on 23 Dec 2016  路  17Comments  路  Source: swimlane/ngx-datatable

I'm submitting a ... (check one with "x")

[x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here

Current behavior
If the input rows are re-ordered, the visualization of the table is not updated.

Expected behavior
If the input rows are re-ordered, I would expect the view to reflect this change.

Reproduction of the problem
In the following component, select the second row and click the "Up" button.

Expected behaviour: first row in table is "b", second row in table is "a"
Actual behaviour: Table does not change (first row "a", second row "b").

import { Component } from '@angular/core'

@Component({
  selector: 'table-test',
  template: `
  <swui-datatable 
      class="material"
      [rows]="rows" 
      [selected]="selected"
      [selectionType]="'single'">
        <swui-datatable-column name="Prop" prop="prop" [sortable]="false">
        </swui-datatable-column>
    </swui-datatable>
  <button (click)="clickUp()">Up</button>
  `
})

export class StartComponent {
  selected :any[] = []
  rows = [ { prop: 'a' }, { prop: 'b' } ]

  clickUp() {
    console.log(JSON.stringify(this.rows))
    let ix = this.getSelectedIx()
    let arr = [ ...this.rows ]
    arr[ix-1] = this.rows[ix]
    arr[ix] = this.rows[ix-1]
    this.rows.splice(0, this.rows.length, ...arr)
    console.log(JSON.stringify(this.rows))
  }

  getSelectedIx() {
    return this.selected[0]['$$index']
  }
}

What is the motivation / use case for changing the behavior?
The user should be able to choose the order of a table arbitrarily.

  • Table version: 2.2.3

  • Angular version: 2.4.0

Investigate Need More Info

All 17 comments

Note: adding this.rows.push({ prop: 'x' }) to the end of clickUp() causes the view to update with rows "b", "a", "x", which has the correct order for "b", "a", but a superfluous "x".

Works for me- See: https://github.com/swimlane/ngx-datatable/blob/master/demo/selection/selection-single.ts

You copied your rows but never set the rows back to the collection.

I think there is a misunderstanding - this has nothing to do with selection, but rather the fact that the Array.prototype.splice function does not cause the table to update (in contrast e.g. to the Array.prototype.push function).

Please consider the following more minimal example:

import { Component } from '@angular/core'

@Component({
  selector: 'table-test',
  template: `
  <ngx-datatable
      class="material"
      [rows]="rows">
        <ngx-datatable-column name="Prop" prop="prop" [sortable]="false">
        </ngx-datatable-column>
  </ngx-datatable>
  <button (click)="click()">Switch</button>
  `
})

export class StartComponent {
  rows = [ { prop: 'a' }, { prop: 'b' } ]

  click() {
    console.log(JSON.stringify(this.rows))
    let arr : any[] = []
    arr.push( this.rows[1] )
    arr.push( this.rows[0] )
    this.rows.splice(0, this.rows.length, ...arr)
    console.log(JSON.stringify(this.rows))
  }
}

Clicking "Switch" causes the this.rows variable to have changed content.
Before: [{"prop":"a","$$index":0},{"prop":"b","$$index":1}]
After: [{"prop":"b","$$index":1},{"prop":"a","$$index":0}]

But the view does not update - still the first row displays 'a', the second row displays 'b'.

Note that if the line arr.push( this.rows[1] ) is removed, then the view does update (showing only 'a'). Hence I believe that there is a bug in the fact that re-ordering/permutation of rows is not recognized as a change.

Could this issue be reopened, please? (I do not think that I can do that myself.)

Sure, can you make a demo?

Sure: http://plnkr.co/edit/8ieWISBXrrzwuW290QdS?p=preview

The "Switch" button switches the first two rows in the table. The view does not update.
The "Add" button switches the first two rows in the table and adds a row at the bottom. The view does update.

Thanks for looking into it.

Would the issue not be because the change detection is set to onPush thus it does not update till something is pushed to it.

@Tempus35: Thanks for your input!

I don't think that's the issue, though: After reading up on onPush here, I understand that if the component had the change strategy onPush, in the demo it would update the view exactly if one would do rows = someOtherArray (with someOtherArray !== rows).

But that does not seem to be the case:

  • in the demo, rows always stays the same object, but
  • the button "Add (works)" manipulates the rows object, and the view updates correctly.

Therefore I conclude that the ngx-datatable component does not have onPush change detection.

A search through the code seems to confirm that: some subcomponents have onPush (like datatable-progress), but the main component seems to have a different change detection strategy.

OnPush is a down-ward setting until explicitly overridden.

From my point of view, this issue is still open - I do not believe that onPush is relevant here, see above.

Is there any more information I can provide?

This seems to be related to my problem. In my case the view also doesn't get updated. I could figure out that using rows.push(...) after manipulating the rows array also worked like in your case. #486 Did you find a solution for that?

You need to use the rowIdentity function. https://github.com/swimlane/ngx-datatable/blob/master/docs/api/table/inputs.md#rowidentity

Can you update and confirm that works?

@amcdnl: Thanks for the feedback!

I updated the example: http://plnkr.co/edit/aVjswgvVQQ9muS7ySJKb?p=preview

Unfortunately, it does not seem to work: the rowIdentity function does not seem to be called (there is no console.log ouput). The suggestion apparantly does not help, sorry :-/

Tried it here: http://plnkr.co/edit/JrlPmfS0RD5OiV2pNP1u?p=preview

Did not work, unfortunately.

Is there any update on this issue, I'm having the same problem :frowning_face:

Is there a workaround to force redraw?

Please reopen if this is still an issue.

Was this page helpful?
0 / 5 - 0 ratings