来自木偶的嵌套元素的平面列表

时间:2014-08-12 11:11:44

标签: backbone.js marionette

Marionette是否可以从嵌套的模型和集合列表中生成一个平面列表?

例如,我想生成一个select元素,每个节点作为一个选项(子选项应该缩进):

[
  {
    nodeName: "top level 1",
    nodes: [
      {
        nodeName: "2nd level, item 1",
        nodes: [
          { nodeName: "3rd level, item 1" },
          { nodeName: "3rd level, item 2" },
          { nodeName: "3rd level, item 3" }
        ]
      },
      {
        nodeName: "2nd level, item 2",
        nodes: [
          { nodeName: "3rd level, item 4" },
          { nodeName: "3rd level, item 5"},
          { nodeName: "3rd level, item 6" }
        ]
      }
    ]
  }
]

这应该是:

<select>
    <option>top level 1</option>
    <option>   2nd level, item 1</option>
    <option>      3nd level, item 1</option>
    <option>      3nd level, item 2</option>
    <option>      3nd level, item 3</option>
    <option>   2nd level, item 2</option>
    ...
</select>

到目前为止,我一直在尝试嵌套的复合视图(如同这个小提琴http://jsfiddle.net/hoffmanc/NH9J6/),但我无法使其正常工作。

此致

2 个答案:

答案 0 :(得分:1)

当然,首先递归迭代嵌套并使用节点文本和嵌套级别创建普通JSON进行填充:

var flat = [];

function parseJson(nodes){
    parseJson.level = parseJson.level || 0;        

    nodes.forEach(function(node, i){
        flat.push({ text:node.name, level: parseJson.level});
        if(node.nodes){
            parseJson.level++;
            parseJson(node.nodes);
        } 
        (i == nodes.length -1) && parseJson.level--;
    })
}

/* or you can get flat array with reduce */

var rawJson = [/* Your json here */], 
    flat = rawJson.reduce(function rec(memo, item, i, array){
        rec.level = rec.level || 0;
        memo.push({ text: item.n, level: rec.level });
        if(item.nodes){
            rec.level++;  
            item.nodes.reduce(rec, memo);
        }

        (i == array.length -1) && rec.level--;

        return memo;
}, []);

nodes是你的原始json。在flat中,您将拥有以下元素:

{
    text: 'node text',
    level: 2
}

接下来,为视图渲染创建模型和集合:

var NodeModel = Backbone.Model.extend({
        defaults: {
            name: 'unnamed',
            level: 0
        }
    }),
    NodeCollection = Backbone.Collection.extend({
        model: NodeModel 
    });

然后观看:

var NodeView = Marionette.ItemView.extend({
        tagName: 'option',
        template: '#node-template'
    }),
    NodeCollectionView =  Marionette.CollectionView.extend({
        itemView: NodeView /* or childView if Marionette v 2.0.*/
    });

然后模板:

<% _.times(level, function(){ %> &nbsp; <% }); %> <%= text %>

最后:

(new NodeCollectionView({
  collection: new NodeCollection(flat),
  el: 'body'
})).render();

多数民众赞成希望这有帮助;

答案 1 :(得分:0)

您是否考虑过使用underscore.js的_.flatten()方法?它可能会简单得多。 flattening nested arrays/objects in underscore.js