将选项从CollectionView传递到递归CompositeView

时间:2013-05-08 16:50:02

标签: javascript marionette backbone-views

我正在做一些与本文中描述的树结构非常相似的东西:

http://lostechies.com/derickbailey/2012/04/05/composite-views-tree-structures-tables-and-more/

我们的想法是在集合视图(TreeRoot)中拥有一组根节点,其中每个根节点也有一个递归的复合视图(TreeView)。可以在这里找到一个jsFiddle,它显示了来自aricle的树结构的最简单的工作示例:

http://jsfiddle.net/hoffmanc/NH9J6/

我想修改示例,以便可以将一些选项传递给每个树视图,而不管它在树结构中的位置。这是我的(仅略微修改)jsFiddle:

http://jsfiddle.net/QL4AE/1/

我修改过的例子中的JS代码是:

// The recursive tree view
var TreeView = Backbone.Marionette.CompositeView.extend({
    template: "#node-template",

    tagName: "li",

    initialize: function(){
        // grab the child collection from the parent model
        // so that we can render the collection as children
        // of this parent node
        this.collection = this.model.nodes;
        console.log(this.options.msg); // undefined!
    },

    appendHtml: function(cv, iv){
        cv.$("ul:first").append(iv.el);
    },
    onRender: function() {
        if(_.isUndefined(this.collection)){
            this.$("ul:first").remove();
        }
    }
});

// The tree's root: a simple collection view that renders 
// a recursive tree structure for each item in the collection
var TreeRoot = Backbone.Marionette.CollectionView.extend({
    tagName: "ul",
    itemView: TreeView
});



// ----------------------------------------------------------------
// Below this line is normal stuff... models, templates, data, etc.
// ----------------------------------------------------------------
treeData = [
  {
    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",
              nodes: [
                  { nodeName: "4th level, item 1" },
                  { nodeName: "4th level, item 2" },
                  { nodeName: "4th level, item 3" }
              ]
          },
          { nodeName: "3rd level, item 6" }
        ]
      }
    ]
  },
  {
    nodeName: "top level 2",
    nodes: [
      {
        nodeName: "2nd level, item 3",
        nodes: [
          { nodeName: "3rd level, item 7" },
          { nodeName: "3rd level, item 8" },
          { nodeName: "3rd level, item 9" }
        ]
      },
      {
        nodeName: "2nd level, item 4",
        nodes: [
          { nodeName: "3rd level, item 10" },
          { nodeName: "3rd level, item 11" },
          { nodeName: "3rd level, item 12" }
        ]
      }
    ]
  }

];


TreeNode = Backbone.Model.extend({
    initialize: function(){
        var nodes = this.get("nodes");
        if (nodes){
            this.nodes = new TreeNodeCollection(nodes);
            this.unset("nodes");
        }
    }        
});

TreeNodeCollection = Backbone.Collection.extend({
    model: TreeNode
});

var tree = new TreeNodeCollection(treeData);
var treeView = new TreeRoot({
    collection: tree,
    itemViewOptions: {msg: 'hi'}
});

正如您所看到的,我正在尝试使用itemViewOptions传递选项,但是当TreeView初始化时,它不存在。我假设这是因为只有TreeRoot获取itemViewOptions。

我的问题是:如何将TreeRoot中的选项传递给TreeView?

谢谢!

1 个答案:

答案 0 :(得分:0)

由于UI要求(需要在表中包含树),我们最终会采用稍微不同的实现方式。我们使用一个名为treetable的jQuery插件在表中创建一个树。在下面的示例代码中,集合视图只是一组项视图(项视图直接附加到DOM)。每个有子节点的节点都为它们创建一个新的集合视图。需要将ItemView el附加到的jQuery对象传递给每个ItemView。

<强>的Javascript

var NodeView = Backbone.Marionette.ItemView.extend({
    tagName: "tr",
    template: "#node-template",

    onRender: function() {

        var parent   = this.model;
        var children = parent.nodes;
        var table    = this.options.table;

        if (!table) {
            throw "No table element passed. Nowhere to append rows!";
        }

        table.append(this.el);

        if (children !== undefined) {
            // create and render new collection view for children nodes
            var childrenView = new TreeRoot({
                collection: children,
                parent: parent,
                table: table
            });
            childrenView.render();
        }
    }
});


var TreeRoot = Backbone.Marionette.CollectionView.extend({
    itemView: NodeView,

    itemViewOptions: function() {
        return {
            table: this.options.table
        }
    },

    appendHtml: function(collectionView, itemView, index){

        /*
        * Set custom attributes needed by TreeTable jQuery plugin
        */

        var model = itemView.model;
        $(itemView.el).attr("data-tt-id", model.get("nodeName"));

        var parent = collectionView.options.parent;
        if (parent !== undefined) {
            $(itemView.el).attr("data-tt-parent-id", parent.get("nodeName"));
        }
    }

});



// ----------------------------------------------------------------
// Below this line is normal stuff... models, templates, data, etc.
// ----------------------------------------------------------------
treeData = [
  {
    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",
              nodes: [
                  { nodeName: "4th level, item 1" },
                  { nodeName: "4th level, item 2" },
                  { nodeName: "4th level, item 3" }
              ]
          },
          { nodeName: "3rd level, item 6" }
        ]
      }
    ]
  },
  {
    nodeName: "top level 2",
    nodes: [
      {
        nodeName: "2nd level, item 3",
        nodes: [
          { nodeName: "3rd level, item 7" },
          { nodeName: "3rd level, item 8" },
          { nodeName: "3rd level, item 9" }
        ]
      },
      {
        nodeName: "2nd level, item 4",
        nodes: [
          { nodeName: "3rd level, item 10" },
          { nodeName: "3rd level, item 11" },
          { nodeName: "3rd level, item 12" }
        ]
      }
    ]
  }

];


TreeNode = Backbone.Model.extend({
    initialize: function(){
        var nodes = this.get("nodes");
        if (nodes){
            this.nodes = new TreeNodeCollection(nodes);
            this.unset("nodes");
        }
    }        
});

TreeNodeCollection = Backbone.Collection.extend({
    model: TreeNode
});

var tree = new TreeNodeCollection(treeData);

var table = $('#tree');

var treeView = new TreeRoot({
    collection: tree,
    table: table
});

treeView.render();

table.treetable({ expandable: true });

<强> HTML

<html>
    <head>
        <link href="https://raw.github.com/ludo/jquery-treetable/master/stylesheets/jquery.treetable.css" rel="stylesheet" type="text/css" />
        <link rel="stylesheet" href="https://raw.github.com/ludo/jquery-treetable/master/stylesheets/jquery.treetable.theme.default.css">
    </head>
    <body>
        <script src="https://raw.github.com/documentcloud/underscore/master/underscore-min.js"></script>
        <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
        <script src="https://raw.github.com/documentcloud/backbone/master/backbone-min.js"></script>
        <script src="https://raw.github.com/derickbailey/backbone.marionette/master/lib/backbone.marionette.js"></script>
        <script src="https://raw.github.com/ludo/jquery-treetable/master/javascripts/src/jquery.treetable.js"></script>

        <script id="node-template" type="text/template">
            <td><%= nodeName %></td>
        </script>

        <table id="tree">
            <thead>
                <tr>
                    <th>Name</th>
                </tr>
            </thead>
            <tbody>
            </tbody>
        </table>

        <script src="tree.js"></script>
    </body>
</html>