EmberJS - Table 带有多个复选框 - 如何使用分页保留 'checked' 状态

EmberJS - Table with multiple checkboxes - how to preserve 'checked' status with pagination

这是我的组件模板 sortable-table-checkbox.hbs

<table class="table table-checkbox" data-page-length="{{dataPageLength}}">
  <thead>
    <tr>
      <th>&nbsp;</th>
      {{#each-in columns as |prop value| }}
        <th
          class="{{if (or (eq (get sortingStatus prop) '')
                          (eq (get sortingStatus prop) 'asc')
                          (eq (get sortingStatus prop) 'desc')) 'sorting'}} w25p {{get sortingStatus prop}}"
          {{action 'toggleSorting' prop}}>
          {{#if value.title}}
            {{value.title}}
          {{else}}
            {{value}}
          {{/if}}
        </th>
      {{/each-in}}
    </tr>
  </thead>
  <tbody>
  {{#each data as |item|}}
    <tr>
      <td>
        <div class="">
          {{input
              type='checkbox'
              checked=item.checked
              change=(action 'chooseItem' item)}}

        </div>
      </td>
      {{#each-in columns as |prop value| }}
        <td>
          {{#collection- value=(get item prop) field=value.field as |col|}}
            {{#number-format isNumber=(eq value.type 'number') value=col as |val|}}
              {{#if value.linkable}}
                {{#link-to value.linkable.route (get item value.linkable.paramField)}}
                  {{value.prefix}}
                  {{val}}
                {{/link-to}}
              {{else}}
                {{value.prefix}}
                {{val}}
              {{/if}}
            {{/number-format}}
          {{/collection-}}
        </td>
      {{/each-in}}
    </tr>
  {{/each}}
  </tbody>
</table>

<p>Your Selected Items:</p>
<ul>
  {{#each selectedItems as |item|}}
    <li>{{item.title}}</li>
  {{else}}
    <em>No items selected</em>
  {{/each}}
</ul>

{{checked}}


{{yield}}

这是我的组件 sortable-table-checkbox.js

import Ember from 'ember';

/**
 * Table component
 *
 * Allows to render dynamic tables with sorting where items are displayed as
 * checkboxes
 *
 * Header titles of table should passed as ``columns`` arg to the component.
 *
 * columns: {
 *   title: {
 *     title: 'Game Title',
 *     sorting: 'title',
 *     linkable: {
 *       route: 'home.cabinet.developer.games.game',
 *       paramField: 'game_uid',
 *     },
 *   },
 *   genres: {
 *     title: 'Genre',
 *   },
 *   amount: {
 *     title: 'Ad Revenue Earned',
 *     prefix: '$',
 *     type: 'number',
 *     sorting: 'amount'
 *   },
 *   platforms_data: {
 *     title: 'Platform',
 *     collection: true,
 *     field: 'title',
 *   },
 *   ages_data: {
 *     title: 'Ages',
 *     collection: true,
 *     field: 'value',
 *   },
 * },
 *
 * Example of using of this component
 *
 * {{sortable-table data=model.games.results columns=columns sorting=sorting}}
 *
 * @class SortingTableComponent
 * @module components/sortable-table
 * @extends Ember.Component
 * @public
 */
export default Ember.Component.extend({

  /**
   * Sorting status
   *
   * @property sortingStatus
   * @type {Object}
   * @default null
   * @public
   */
  sortingStatus: null,

  /**
   * Avoid sharing state between components
   *
   * @method init
   * @return {undefined}
   * @public
   */
  init() {
    this._super(...arguments);
    this.set('sortingStatus', {});
    this.selectedItems = [];
    this.checked=false;
  },

  /**
   * Fill ``sortingStatus`` object with reset statuses
   *
   * @method willInsertElement
   * @return {undefined}
   * @public
   */
  willInsertElement() {
    const columns = this.get('columns');

    for (const element in columns) {
      if (columns[element].sorting) {
        this.set(`sortingStatus.${element}`, '');
      }
    }
  },

  actions: {

    /**
     * Toggle sorting
     *
     * @method toggleSorting
     * @param prop {String} name of property
     * @return {boolean} false if this property doesn't exist in ``sorting`` object
     * @public
     */
    toggleSorting(prop) {
      // If ``prop`` property doesn't exist in ``sorting`` object, return false
      if (!(prop in this.get('sortingStatus'))) {
        return false;
      }

      // Reset another properties sorting state
      for (const element in this.get('sortingStatus')) {
        if (element !== prop) {
          this.set(`sortingStatus.${element}`, '');
        }
      }

      // Set asc if starting state, desc if asc and starting state if desc
      if (this.get(`sortingStatus.${prop}`) === '') {
        this.set(`sortingStatus.${prop}`, 'asc');
      } else if (this.get(`sortingStatus.${prop}`) === 'asc') {
        this.set(`sortingStatus.${prop}`, 'desc');
      } else {
        this.set(`sortingStatus.${prop}`, '');
      }

      // Sending action
      this.sendAction('action', this.get(`columns.${prop}.sorting`), this.get(`sortingStatus.${prop}`));

      return true;
    },

    chooseItem(item, e) {
      const added = e.target.checked;
      this.set('checked', added);
      if (added) {
        item.checked=true;
        this.get('selectedItems').pushObject(item);
      }
      else {
        this.get('selectedItems').removeObject(item);
      }
    },
  },
});

因此,当我浏览页面时,应用程序会 API 调用查询要显示的下 5 个项目,当我返回第 1 页时,我没有 item.checked 状态 - 因为项目是来自 API 调用的新对象,因此它没有我在 chooseItem 中设置的 .checked 属性动作。

如何解决这个问题?

也许有一个动态的方法来检查是否可以设置复选框的 checked 属性?

这些更改未保存,因为您没有在后端保存带有正确选中字段的模型。我建议两种动态计算复选框选中状态的方法:

  1. 快的那个。您可以 create a custom helper to check that element is in array. Or you can use any existing addon 提供这样的帮手。然后你可以在sortable-table-checkbox.hbs中这样写:

    {{input type='checkbox' 
    checked=(array-contains selectedItems item.id property='id') 
    change=(action 'chooseItem' item)}}

  1. 您可以创建一个组件 table-row 并将您在 <tr></tr> 中的所有内容移动到 sortable-table-checkbox.hbs。该组件将具有 itemselectedItems 作为参数。然后你可以使用 Ember 计算属性:

      //table-row.js
      // ...
      isChecked: Ember.computed('item.id', 'selectedItems.length', function() {
          const itemId = this.get('item.id');
          const selectedItems = this.get('selectedItems');
          return selectedItems.some(el => el.get('id') === itemId);
      })
      // ...


    //table-row.hbs
    {{input type='checkbox'
            checked=isChecked
            change=(action 'chooseItem' item)}}