Создание сортируемого пользовательского тега теряет видимость

У меня есть список объектов (файлов каталогов). Затем пользователь может выбрать порядок сортировки (имя, дата и т. д.) и добавить дополнительные элементы.

После сортировки наблюдатель правильно обновляет данные, и пользовательский тег обновляется. Однако, когда я добавляю новые элементы, пользовательский тег не получает тот же триггер обновления.

Мой собственный тег {{sort}} в основном делает следующее:

  1. Зацикливает и преобразует список объектов в массив (для возможности упорядочения).
  2. Сортирует массив по предоставленному индексу (имя и т. д.).
  3. Зацикливает и создает HTML-код рендеринга.

Мои данные:

{
    'file1-id' : { name : 'file.txt', date : 1470123456 },
    ...
}

Мой HTML:

{^{sort prop.items ~root.sort.index ~root.sort.direction}}
    {^{:item.name}}
{{/sort}}

Мой JS:

$.views.tags({
    /**
     * @usage   {^{sort items keyname desc}} {{:i}}{{:key}}{^{:item.property}} {{/sort}}
     * 
     * @param   mixed   $items      An Object of Items to Loop & Render.
     * @param   string  $index      The Name of the Item Key to Order by (name|date|size.x).
     * @param   string  $direction  The Direction to Order by (asc = old -> new, desc = new -> old).
     */
    sort : function( items, index, direction )
    {
        var results     = [];
        var segments    = index.split( '.' );
        var deep        = segments.length > 1; // Check whether a nested index ( e.g. size.x)

        // Render Each Item to an Array
        $.each( items, $.proxy( function( key, el )
        {
            // Skip jQuery Observer Event Items Which are in the List (jQuery12313847623846)
            if( !el.data || !el.events )
            {
                var keyval = null;

                // Search for nested index
                if( deep && el.hasOwnProperty( segments[0] ) && el[segments[0]].hasOwnProperty( segments[1] ) )
                {
                    var keyval = el[segments[0]][segments[1]];
                }
                else if( el.hasOwnProperty( segments[0] ) )
                {
                    var keyval = el[segments[0]];
                }//end if

                // Keep Hold of Keys for Sorting
                results.push(
                {
                    key     : keyval,
                    item    : el
                });
            }//end if
        }, this ) );

        // Sort Items
        if( segments[0] )
        {
            results = results.sort( function( a, b )
            {
                if( direction == 'asc' )
                {
                    return a.key > b.key ? 1 : -1;
                }
                else
                {
                    return a.key < b.key ? 1 : -1;
                }//end if
            });
        }//end if

        // Traverse, Render Item HTML, Implode & Return
        return $.map( results, $.proxy( function( el, i )
        {
            return this.tagCtx.render( { i : i, key : el.key, items : results, item : el.item } );
        }, this ) ).join( "\n" );
    },
});

Преобразование объекта в массив теряет наблюдаемость или проблема заключается в чем-то другом?

Я просмотрел документы, но не смог найти ни одного сценария, похожего на мой, кроме контроль диапазона.

Я ограничен следующим:

  • Данные представляют собой список объектов и могут быть массивом объектов.
  • JSViews v1.0.0-alpha 52 (знаю, не последняя!).

Я попытался использовать свойства тега для восстановления наблюдаемости, например:

boundProps : ['items', 'index', 'direction'],
dataBoundOnly : true,
autoBind : true,

Это упрощенный пример. Если ошибка изначально не очевидна, я попытаюсь сделать скрипку. Любые указатели будут очень признательны!

Спасибо!


person Paul    schedule 15.05.2017    source источник


Ответы (1)


Ваш собственный тег {{sort}} — это всего лишь функция, то есть просто метод рендеринга. Чтобы обеспечить полный наблюдаемый контроль, вам нужно больше...

В этом случае вы хотите, чтобы тег брал хэш объектов элементов и отображал его как наблюдаемую коллекцию элементов. Способ сделать это — использовать функцию JsViews Observable Map, которая сопоставляет наблюдаемые данные, основанные на одной модели, с наблюдаемыми данными, основанными на другой модели.

Observable Map еще не полностью задокументирована, но вы можете увидеть, как она используется в следующих примерах:

Простая отсортированная таблица Grid

Ярлык:

{^{forPlus list.rows ^sortby=list.sortby ^reverseSort=list.reverseSort ~list=list}}

Код:

$.views.tags({
    forPlus: {
        baseTag: "for",
        dataMap: $.views.map({
            getTgt: getTargetItems,
            obsSrc: observeSourceItems
        }),
        onUpdate: function() {
            this.tagCtx.map.update();
        }
    }
});

Сетчатые представления отсортированных таблиц (более сложный пример):

Тег JsViews {{props}}, который отображает объект в массив (массив свойств):

Более сложный случай: сортируемый тег {{forHash}}, который преобразует наблюдаемый хэш объектов элементов в наблюдаемый массив элементов — аналогично вашему дизайну данных и сценарию выше. См. образец здесь:

person BorisMoore    schedule 18.05.2017
comment
Ух ты! Итак, как мне получить доступ к отдельным данным внутри {^{forPlus}}, а не использовать {^{props}} для общего вывода данных. Я пробовал {^{:prop.id}} и {^{:id}}, но они не работают. Я не могу понять, как {^{props}} знает, что доступно, просматривая ваш пример и jsviews? - person Paul; 18.05.2017
comment
Также, чтобы уточнить, я вижу, что {^{:id}} и {^{:name}} работают, когда list.rows является массивом объектов, но когда я преобразовываю пример jsfiddle в список объектов, я не могу понять, что мне не хватает для рендеринга строк? - person Paul; 18.05.2017
comment
Я добавил ссылку на новый пример, который похож на ваш сценарий выше и должен помочь понять, как работает карта наблюдаемых данных JsViews. - person BorisMoore; 20.05.2017
comment
Вы, сэр, легенда! С нетерпением жду документации, так как это действительно очень мощная структура для поиска без посторонней помощи. - person Paul; 22.05.2017