Enterprise-ng: Row selection is lost with a standalone pager

Created on 23 Apr 2019  路  23Comments  路  Source: infor-design/enterprise-ng

Describe the bug

When using a standalone pager (soho-standalone-pager) selections are not retained when navigating between pages.

Setting allowSelectAcrossPages to true does not work (and is also not exposed as an Input) as this only works if the source and pager members are set in the data grid.

To Reproduce

Using the datagrid-standalone-pager example, modify the code to clone the data emulating data being passed back from a server (which does not contain the selected state).

  const cloned = this.data.map(x => Object.assign({}, x));

  const result: any = {
    data: cloned.slice(this.beginIndex, this.endIndex),
    firstPage: this.beginIndex === 0,
    lastPage: this.endIndex >= this.data.length - 1
  };
npm run build:lib
npm run start

Navigate to http://localhost:4200/ids-enterprise-ng-demo/datagrid-standalone-pager.

Select rows and move forward and back.

Expected behavior

When moving between pagers, it should be possible to get the datagrid to keep any selections as if the pager was created by the datagrid itself.

Version

  • ids-enterprise-ng: 5.2

Screenshots
N/A

Platform
All

Additional context

[5] type

Most helpful comment

Nothing wrong with playing devil's advocate. We use a state model to hold the current selection/page/row so we can drive the data grid using @Inputs rather than a source function.

This allows us to use the same state model in different views and also to decouple the model view and controller aspects.

It's close to working, if we could tell the data grid paging is being handled by the client (using a standalone pager) that may help.

All 23 comments

@tmcconechy - not sure if this is more a bug for the ep controls, as the logic for syncing the selection is there.

@bthharper It seems ok to me on the EP example though? http://master-enterprise.demo.design.infor.com/components/datagrid/test-paging-multiselect-select-across-page.html Does it not?

Also the input would be here. Im guessing the problem is that you clone. I think i'm holding the references.

@tmcconechy - looking at the EP code, the sync selected methods are not called when the pager is not set (and possibly some other state too), and in the case of a standalone pager these are not set.

I added the clone to emulate a real backend services returning pages, where as the demo just keeps a list in memory and returns slices of it. This isn't something you get when using a backend.

Can we expose the "sync function" ?

OK, makes sense. I think we could expose syncSelectedRows, but might be better to put it in the callback function or loadRows so it gets called during paging? Are you saying you could reproduce it in EP only?

I've not tried it in EP only, but it's not an issue with NG really, more a case the standalone pager does not integrate with the datagrid in the same was as an embedded one.

We call loadData like this when the input data changes:

@Input() set data(data: any[]) {
    this.gridData = data;
    if (data && this.jQueryElement) {

      this.ngZone.runOutsideAngular(() => {
        // @todo add hints for this too, as other changes may force a rebuild?
        this.datagrid.loadData(data);
      });
    }
  }

So maybe using allowSelectAcrossPages in loadData would work?

@tmcconechy - we've rolled our own code to keep selections whilst paging, however we need some tighter integration with the datagrid to allow the selection checkbox to be interacted with, that is:

  • an event when the item is clicked.
  • the ability to set the state to 'partial'

Thoughts?

I'll add the 'type' argument into the datagrid component, that will help.

type SohoDataGridSelectedEventType = 'deselectall' | 'selectall' | 'select' | 'deselect';

interface SohoDataGridSelectedEvent {
  e: JQuery.TriggeredEvent;
  rows: SohoDataGridSelectedRow[];

  /** What was the action that caused the event? */
  type: SohoDataGridSelectedEventType;
}

I might look to add a method to set the selection state - we can always change it to use the correct api later.

Sure it should be fairly straightforward to move that code https://github.com/infor-design/enterprise/blob/master/src/components/datagrid/datagrid.js#L6983-L6995 to a method fx setHeaderCheckboxState or something

@tmcconechy - unfortunately the change does not quite work as I hoped. The problem is that the (selected) event is fired on paging (we call loadData) - with the extra argument of 'deselectall'. In our event handler I cannot determine if the source of the event was a call to loadData or the user clicking on the deselect all checkbox.

Looking at the code, this is because there is no pagerinfo on the datagrid.

Ok whats your suggestion then? Do we need to look at this in the next sprint again?
Also to play the devils advocate here, why cant we just use the paging feature in the normal way which works ok? I.E. Curious whats driving the need to make it seperate?

Also maybe @pwpatton has some suggestions as I did do the standalone pager as requested by their team so I assume this is all working for them.

Nothing wrong with playing devil's advocate. We use a state model to hold the current selection/page/row so we can drive the data grid using @Inputs rather than a source function.

This allows us to use the same state model in different views and also to decouple the model view and controller aspects.

It's close to working, if we could tell the data grid paging is being handled by the client (using a standalone pager) that may help.

@bthharper agreed, sometimes the pagerInfo has gotten in the way with this technique. It would be nice to be able to completely remove it as a consideration in the datagrid with some option:

gridOptions.noPaging = true;

OK could you put together something i could look at? Im not 100% sure if i follow the last issue.
But as per @pwpatton we have paging: false ? That means dont consider a paging is involved.

@tmcconechy Yes, we could make a nice sample in ids-ng. It's a super simple technique.

Yep - the problem I have is that the datagrid fires selected([], 'deselectall') when calling loadData if the pagerInfo member variable is undefined.

This means I can't detect the user pressing header selection box using that second argument as we first thought, as paging deselects all the rows.

If we could tell the datagrid the rows are being paged by the client perhaps?

I'll try and knock together an example, using the existing standalone paging example.

We have this issue also and got around it somehow. (don't remember how).

I did think of inspecting the event, but this just seems too brittle.

I'll have a look at your example and see about it.

I've worked around this in our code by keeping track of selected rows.

We have a datagrid option selectRowsAcrossPages that will do that for serverside paging. This may also help as it keeps track. But i didn't try it with standalone pager.

https://master-enterprise.demo.design.infor.com/components/datagrid/test-paging-multiselect-select-across-page.html

Closing this for now - but working this into the web component version. The pager will be just a dumb component with events.

Was this page helpful?
0 / 5 - 0 ratings