DGarvanski DGarvanski - 3 months ago 88
TypeScript Question

Persist PrimeNG DataTable selection on route change

I'm using a PrimeNG data table in an Angular 2 application and I have to persist the selection on route change. Currently, I'm setting the app state like so:

onTableRowStateChange() {
this.appState.set('selectedApplicants', this.selectedApplicants);
}


Where appState is a service that saves the selection state. This is also used to persist some tabs which open up on selection.

While the appState is correctly set, returns an array of selected applicants and persists opened tabs, it does not persist the actual selection in the data table thus entries can be selected again.

The HTML looks like this:

<p-dataTable tableStyleClass="table" [value]="applicants"
[(selection)]="selectedApplicants"
(onRowSelect)="onTableRowStateChange()"
(onRowUnselect)="onTableRowStateChange();">
<header>Applications</header>
<p-column [style]="{'width':'38px'}" selectionMode="multiple"></p-column>
<p-column *ngFor="let col of cols" [field]="col.field" [header]="col.header"></p-column>
</p-dataTable>


I tried using a
this.appState.get('selectedApplicants')
method to get the
selectedApplicants
array during `ngOnInit, in the constructor and even setting it like so:

selectedApplicants:any[] = ( this.appState.get('selectedApplicants').length > 0 ) ? this.appState.get('selectedApplicants') : this.appState.set('selectedApplicants', []);


in the component.

However, while it does return an array of selected applicants it doesn't select them in the table itself.

As a side note, doing
this.selectedApplicants.splice(event.index, 1);
on closing the tab deselects the table entry, so it is possible to programatically change selection by altering the selected entries array. It just doesn't select the entries automatically on initiating the view after a route change even if the required array is present.

Is there a workaround or any way to persist the data table selection on route change?

Answer

Found my problem. I was initializing the array, which was used in the DataTable [value] attribute, during ngOnInit. Hence, the selection, value and, in this case, applicants arrays all basically carried different objects (while carrying the same data) on every view initialization.

What I did before that was push the objects from the selectedApplicants array into the table selection and value arrays. While it did work, it was not a good option with having to do two forEach loops before I could clear the table's arrays and push the saved objects from the app state into them. That was not awful for two-three objects but if I had to deal with more it would have slowed down the app immensely.

So, the solution was to use this:

applicants:any[] = ( this.appState.get('applicants').length > 0 ) ? this.appState.get('applicants') : this.appState.set('applicants', this.getApplicants());

And then check if there are applicants present and set appState on init if they are not.

if (this.appState.get('applicants').length < 1) {
  this.appState.set('applicants', this.getApplicants())
}

This preserves the same arrays from before the route change by getting them from the appState and re-initializes them only when it needs to.