Aurelia

时间:2017-02-22 08:08:31

标签: javascript aurelia

我在这里找到了一个例子https://jdanyow.github.io/aurelia-converters-sample/(搜索SortValueConverter) - 只需要以某种方式扩展toView函数:

export class SortValueConverter {
  toView(array, propertyName, direction) {
    var factor = direction === 'ascending' ? 1 : -1;
    return array
      .slice(0)
      .sort((a, b) => {
        return (a[propertyName] - b[propertyName]) * factor
      });
  }
}

这样它不仅可以对每一行进行排序,还可以对它进行排序:

  1. 对每个行组对象进行排序 - 在表行数组中 - 它具有布尔值isGroup:true set
  2. 与排序一起 但是,行本身也应该对行组子进行排序 属于每个群体
  3. 当然这些行也会 需要与他们的组行一起移动,所以他们留在下面 小组排。
  4. 在我的js代码中,我已经将数组弄平了,所以我可以在表格中显示它。 isGroup:true / false标记新组开始时。

    • 机器人(isGroup:true)
    • R2-D2
    • 终止
    • 壁-E
    • 机械战警
    • C-3PO
    • 动物(isGroup:true)

    如何重写排序值转换器(理想情况下)对行组和行组子进行排序,例如。按字母顺序排列的asc / desc。我想它不必使用值转换器完成,但理论上可以直接在js代码中的数组上完成,但我认为最好的解决方案是扩展排序值转换器以支持此行分组也是。

    将此示例保持为"简单"尽可能让我们将行对象减少到最低限度:

    {
       name: 'group or robot name'
       isGroup: true/false
    }
    

    所以,例如。

    [
        {
            name: 'robots',
            isGroup: true
        },
        {
            name: 'R2-D2',
            isGroup: false
        },
        {
            name: 'terminator',
            isGroup: false
        },
        {
            name: 'wall-e',
            isGroup: false
        },
        {
            name: 'robocop',
            isGroup: false
        },
        {
            name: 'C-3PO',
            isGroup: false
        },
        {
            name: 'animals',
            isGroup: true
        },
        {
            name: 'dog',
            isGroup: false
        },
        {
            name: 'shark',
            isGroup: false
        },
        {
            name: 'cat',
            isGroup: false
        },
        {
            name: 'monkey',
            isGroup: false
        }
    ]
    

    有什么想法吗?

2 个答案:

答案 0 :(得分:2)

我建议稍微更改您的数据结构。您目前拥有的数据结构有点模棱两可,因为列表的排序决定了项目所在的组。我会将结构更改为:

[
  {
    name: 'R2-D2',
    group: 'robots'
  },
  //...

然后,我们可以使用如下所示的值转换器对此数组进行分组和排序:

export class GroupedSortValueConverter {
  toView(value) {

    let sortedArray = value.splice(0).sort((a, b) => {
      const left = a.name,
        right = b.name;

      return caseInsensitiveStringComparer(left, right);
    });

    const groups = new Map();

    for (let item of sortedArray) {
      let group = groups.get(item.group);
      if (group === undefined) {
        groups.set(item.group, [item]);
      } else {
        group.push(item);
      }
    }

    let sortedGroups = new Map(Array.from(groups.entries()).sort((a, b) => {
      const left = a[0];
      const right = b[0];

      return caseInsensitiveStringComparer(left, right);
    }));

    return sortedGroups;
  }
}

function caseInsensitiveStringComparer(left, right) {
  const lowerLeft = left.toLowerCase(),
    lowerRight = right.toLowerCase();

  if (lowerLeft < lowerRight) { //sort string ascending
    return -1;
  } else if (lowerLeft > lowerRight) {
    return 1;
  } else {
    return 0;
  }
}

我们可以使用这样的代码迭代这个Map。请注意,我不得不使用模板元素来包装组中继器,因为转发器没有单一的“自然包装元素”:

<template>
  <require from="./grouped-sort"></require>
  <table>
    <template repeat.for="[group, items] of myArray | groupedSort">
      <tr>
        <td>
          ${group}
        </td>
      </tr>
      <tr repeat.for="item of items">
        <td>
          ${item.name}
        </td>
        </tr>
    </template>
  </table>
</template>

这里有一个可运行的要点:https://gist.run/?id=27a6e61996cb884d97fbeed0acb310bf

请注意,我使用此StackOverflow答案来帮助生成此答案:Is it possible to sort a ES6 map object?

答案 1 :(得分:1)

您可以让转换器为您执行此操作,而不是在将数据提交到值转换器之前展平数据。这样做可以更轻松地对多个条件(组和项名称)进行排序。

我假设您的数据格式与此类似:

let groups = [{
    name: "robots",
    items: ['R2D2', 'terminator', 'wall-e', 'robocop']
}, {
    name: "animals",
    items: ['dog', 'shark', 'cat', 'monkey']
}];

这是值转换器:

export class SortValueConverter {

    toView(array, direction = 'ascending') {
        let factor = direction === 'ascending' ? 1 : -1;
        let arrayToSort = array.slice(0); // Use a copy.

        // Sort the items within each group.
        for (let group of arrayToSort) {
            group.items = group.items.slice(0).sort((a, b) => (a > b ? 1 : -1) * factor); // Sort a copy of the items.
        }

        // Now sort the groups.
        arrayToSort.sort((a, b) => (a.name > b.name ? 1 : -1) * factor);

        // Flatten the result.
        let result = [];

        for (let group of arrayToSort) {
            result.push({name: group.name, isGroup: true});

            for (let item of group.items) {
                result.push({name: item, isGroup: false});
            }
        }

        return result;
    }

}

请注意,为了简单起见,我取出了propertyName参数,但如果您想对其他类似的数据结构执行此操作,则可以轻松添加它以获得更大的灵活性。