创建可排序的自定义标签会失去可观察性

Creating sortable custom tag loses observability

我有一个对象列表(目录文件)。然后用户可以选择排序顺序(姓名、日期等),并添加更多项目。

排序后观察者正确更新数据,自定义标签刷新。但是,当我添加新项目时,自定义标签不会收到相同的刷新触发器。

我的自定义 {{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" );
    },
});

将对象转换为数组会失去其可观察性,还是问题出在其他地方?

我查看了文档,但除了 range control.

之外找不到任何像我这样的场景

我受到以下限制:

我试过使用标签属性来恢复可观察性,例如:

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

这是一个简化的例子,如果错误一开始不是很明显,我会尝试做一个 fiddle。任何指点将不胜感激!

谢谢!

您的自定义 {{sort}} 标签只是一个函数 - 所以只是一个渲染方法。要提供完整的可观察控件,您需要更多...

在这种情况下,您希望标签采用项目对象的对象哈希并将其呈现为可观察的项目集合。这样做的方法是使用 JsViews Observable Map 功能,该功能从基于一个模型的可观察数据映射到基于不同模型的可观察数据。

Observable Map 尚未完全记录,但您可以在以下示例中了解它的使用方式:

简单排序table网格

标签:

{^{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();
        }
    }
});

已排序 Table 网格视图(更复杂的示例):

JsViews {{props}} 标签 - 从对象映射到数组(属性数组):

更高级的情况:一个 sortable {{forHash}} 标签 将项目对象的可观察散列转换为可观察的项目数组 - 类似于您的上面的数据设计和场景。请在此处查看示例: