SlickGrid:如何在分页网格中保留选定的行?

时间:2011-07-20 15:12:56

标签: jquery selection slickgrid

我正在使用SlickGrid的分页版本和CheckboxSelection-Plugin。不幸的是,当一个人离开当前网格页面时行选择会丢失,而当再次访问该页面时不会恢复。也可以使用SlickGrid example #4重现此行为。 (单击网格页脚中的小灯泡图标以打开分页)

我已经通知了SlickGrid的作者,但他没有将这种行为视为一个错误,因为SlickGrid更像是一个网格框架,而不仅仅是一个添加数据解决方案。

有没有人知道如何在SlickGrid中实现可靠的选择持久性,这适用于分页和非分页网格?

4 个答案:

答案 0 :(得分:2)

最后,我通过在示例4中调整grid.onSelectedRowsChanged回调取得了一些成功。关键的区别在于,每次选择更改时我都不会重置全局selectedRowIds数组,因为grid.getSelectedRows()仅限selectedRowIds给我当前页面上的选定行索引。相反,我首先将所有新选择的行添加到grid.onSelectedRowsChanged.subscribe(function (e) { var selRows = grid.getSelectedRows(); // add all newly selected rows to the selection for (var i = 0, l = selRows.length; i < l; i++) { var item = dataView.getItem(selRows[i]); if (item) { var rowId = item.id; if (selectedRowIds.indexOf(rowId) < 0) { selectedRowIds.push(rowId); } } } //check if a previously selected row has been deselected for (var i = 0, l = selectedRowIds.length; i < l; i++) { var row = dataView.getRowById(selectedRowIds[i]); // see if the selected row is available on the current page if (row && selRows.indexOf(row) < 0) { selectedRowIds.splice(i, 1); //remove row from array } } }); 数组,然后迭代它以检查是否已取消选择其当前页面条目之一。

{{1}}

答案 1 :(得分:0)

提案:

  1. 在网格定义之前添加行数组。

    var selectedRows = [];
    
  2. 在pagging事件中,如果行尚未在数组中,则在获取并存储所选行之前:

    function AddRows(grid.getSelectedRows()){//your comparision here};
    
  3. 在paggin事件中设置选定的行:

    grid.setSelectedRows(selectedRows ); 
    
  4. 防止取消选择。如果取消选择行,则获取数组中的行索引,并从数组中删除该行:

    function GetRowSelectedIndex(row);
    var rowIndex = GetRowSelectedIndex(row);
    selectedRows.slice(rowIndex,1);
    

答案 2 :(得分:0)

它工作正常。刚刚修改了上面一个。

                var selRows = grid.getSelectedRows();
                var item = {};
                for (var i = 0; i < selRows.length; i++) {
                    item = dataView.getItem(selRows[i]);
                    if (item != undefined && $.inArray(item.id, selectedRowIds) < 0 ) {
                        selectedRowIds.push(item.id);
                    }
                }
                var removeIds = [];
                var row;
                for (var i = 0; i < selectedRowIds.length; i++) {
                    for (var j = 0; j < selectedRowIds.length; j++) {
                        row = dataView.getRowById(selectedRowIds[j]);
                        if(row != undefined && $.inArray(row, removeIds) < 0){
                            removeIds.push(row);
                            break;
                        }
                    }
                }
                for (var i = 0; i < removeIds.length; i++) {
                    if (removeIds[i] != undefined && $.inArray(removeIds[i], selRows) < 0) {
                        item = dataView.getItem(removeIds[i]);
                        selectedRowIds = $.grep(selectedRowIds, function( a ) { return a !== item.id; });
                    }
                }

答案 3 :(得分:0)

我知道这是一个老问题,但是我必须实现它,并且提议的解决方案不能涵盖所有用例(例如,如果用户转到最后一页,则@fbuchinger提出的解决方案将删除一些选择,而不进行任何操作)选择,然后返回首页)。

为解决此问题,我不得不做一个更复杂的实现,甚至必须添加一个新的DataView事件onBeforePagingInfoChanged,还修改了SlickGrid事件onSelectedRowsChanged以也返回以前的行选择(在当前选择的顶部)。这些更改是在6pac/SlickGrid分支中进行的,并在版本2.4.18下发布了

使用分页时,我使用的步骤如下,我们不能仅使用getSelectedRows(),因为这只会返回当前页面中的选择,这是不够的,我们需要保留一个包含数据的全局数组对象ID(不是行索引,因为它会在页面中不断变化),为保持网格索引和数据ID,我们将在dataView.mapIdsToRows()dataView.mapRowsToIds()之间进行切换。

下面显示的代码步骤如下

  1. 更改行选择时,如果尚未将新选择添加到所选ID的全局数组中,我们将添加新选择
  2. 删除行选择时,我们将从全局选定ID数组中删除选择(除非它来自页面更改)
  3. 在更改页面之前,我们将使用一个标记进行跟踪(在更改页面时,此标记将用于跳过所有删除操作)
  4. 更改页面后,我们将进行额外的(且延迟的)检查,以确保在屏幕上显示我们所选ID的全局数组中的内容
// global variables
_selectedRowDataContextIds = [];     // used with row selection
_wasRecheckedAfterPageChange = true; // used with row selection & pagination

function bindSlickgridEventsForRowSelectionWithPagination() {
this._eventHandler.subscribe(this._dataView.onBeforePagingInfoChanged, () => {
        this._wasRecheckedAfterPageChange = false; // reset the page check flag, to skip deletions on page change (used in code below)
      });

      this._eventHandler.subscribe(this._dataView.onPagingInfoChanged, () => {
        // when user changes page, the selected row indexes might not show up
        // we can check to make sure it is but it has to be in a delay so it happens after the first "onSelectedRowsChanged" is triggered
        setTimeout(() => {
          const shouldBeSelectedRowIndexes = this._dataView.mapIdsToRows(this._selectedRowDataContextIds);
          const currentSelectedRowIndexes = this._grid.getSelectedRows();
          if (!isequal(shouldBeSelectedRowIndexes, currentSelectedRowIndexes)) {
            this._grid.setSelectedRows(shouldBeSelectedRowIndexes);
          }
        });
      });

      this._eventHandler.subscribe(this._grid.onSelectedRowsChanged, (e, args) => {
        if (Array.isArray(args.rows) && Array.isArray(args.previousSelectedRows)) {
          const newSelectedRows = args.rows;
          const prevSelectedRows = args.previousSelectedRows;

          const newSelectAdditions = newSelectedRows.filter((i) => prevSelectedRows.indexOf(i) < 0);
          const newSelectDeletions = prevSelectedRows.filter((i) => newSelectedRows.indexOf(i) < 0);

          // deletion might happen when user is changing page, if that is the case then skip the deletion since it's only a visual deletion
          // if it's not a page change (when the flag is true), then proceed with the deletion in our global array of selected IDs
          if (this._wasRecheckedAfterPageChange && newSelectDeletions.length > 0) {
            const toDeleteDataIds = this._dataView.mapRowsToIds(newSelectDeletions);
            toDeleteDataIds.forEach((removeId) => this._selectedRowDataContextIds.splice(this._selectedRowDataContextIds.indexOf(removeId), 1));
          }

          // if we have newly added selected row(s), let's update our global array of selected IDs
          if (newSelectAdditions.length > 0) {
            const toAddDataIds = this._dataView.mapRowsToIds(newSelectAdditions) || [];
            toAddDataIds.forEach((dataId) => {
              if (this._selectedRowDataContextIds.indexOf(dataId) === -1) {
                this._selectedRowDataContextIds.push(dataId);
              }
            });
          }
          this._wasRecheckedAfterPageChange = true;

          // form our full selected row IDs, let's make sure these indexes are selected in the grid, if not then let's call a reselect
          // this could happen if the previous step was a page change
          const shouldBeSelectedRowIndexes = this._dataView.mapIdsToRows(this._selectedRowDataContextIds);
          const currentSelectedRowIndexes = this._grid.getSelectedRows();
          if (!isequal(shouldBeSelectedRowIndexes, currentSelectedRowIndexes)) {
            this._grid.setSelectedRows(shouldBeSelectedRowIndexes);
          }


          const newSelections = { gridRowIndexes: this._grid.getSelectedRows(), dataContextIds: this._selectedRowDataContextIds };
        }
      });
}

因此在此代码中,变量this._selectedRowDataContextIds具有所选数据对象ID的完整集合。这是一种复杂的方法,但是到目前为止,我发现这是使用网格分页进行的。

请注意,在代码中只有1个lodash函数isequal用于比较2个数组,其他所有内容都是用ES6和TypeScript编写的(尽管我删除了这些类型以提高可读性)< / p>