2017-02-22 11 views
2

Я нашел пример здесь https://jdanyow.github.io/aurelia-converters-sample/ (поиск SortValueConverter) - Просто нужно каким-то образом расширить функции toView:Сортируемые группы рядов (+ группа дочерних строк) с Aurelia

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: истинный набор
  2. Вместе с сортировкой сама строка, она должна, однако, также сортировать детей группы строк принадлежащие по каждой группе
  3. И, конечно, эти строки также должны были бы быть перемещены вместе с их группирования строк, поэтому они остаются ниже группы строк.

В моем js-коде я сплющил массив, поэтому я могу показать его в таблице. isGroup: true/false указывает, когда начинается новая группа.

  • роботы (isGroup: истинно)
  • R2-D2
  • терминатор
  • ВАЛЛ
  • Робокоп
  • С-3PO
  • животных (isGroup: истинные)
  • собака
  • акула
  • кошка
  • обезьяны

Как можно переписать преобразователь значений сортировки (в идеале), чтобы отсортировать обе группы строк и строк группы детей напр. в алфавитном порядке/убывание. Я предполагаю, что это не нужно делать с помощью конвертера значений, но теоретически можно просто сделать непосредственно на массиве в 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

Я бы порекомендовал вам слегка изменить структуру данных. . Структура данных, как вы в настоящее время это несколько неоднозначным, так как упорядочение списка определяет, к какой группе элемент в Я хотел бы изменить структуру, чтобы выглядеть следующим образом:

[ 
    { 
    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; 
    } 
} 

И мы можем перебирать эту карту, используя этот код. Обратите внимание, что у меня использовать шаблон элемент, чтобы обернуть группы повторитель, поскольку нет ни одного «естественного обертывания элемента» для ретранслятора:

<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?

+0

Привет, Эшли, большое спасибо за ваше решение - мы почти там. Я заметил, что он не сортирует элементы внутри групп, поэтому я думал, что могу просто использовать SortValueConverter I, связанный с исходным сообщением, следующим образом: '

  • $ {item.name}
  • '- казалось, не работает. Каким будет лучший способ сортировки элементов внутри групп? – Dac0d3r

    +1

    К сожалению, я забыл это сделать. Я добавлю, что в. –

    +0

    Спасибо! Также я только что заметил. Мне нужно отобразить это как строки в таблице, на том же уровне (сглаженные), как jeff делает, – Dac0d3r

    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; 
        } 
    
    } 
    

    Обратите внимание, что я вынул параметр ИмениСвойства для простоты, но это может быть легко добавляется для большей гибкости, если вы хотите сделать это с другими подобными структурами данных.

    +1

    вы должны проверить мой ответ, где я хвастаюсь поддержкой повторителя для итерации над наборами/картами. –

    +0

    Привет, Джефф, большое спасибо за ваш ответ. Отличное решение - я как раз собирался реализовать это и отметить его как принятый, когда я увидел, что ответ Эшли. Оба - отличные ответы. – Dac0d3r

    +0

    Очень приятно, Эшли. –

    Смежные вопросы