Recursive template with knockout js

后端 未结 4 496
逝去的感伤
逝去的感伤 2020-12-09 02:03

Is it possible to create a recursive template only with knockout js?

I have a knockout object:

function FormElementNode(children, text, value) {
   v         


        
相关标签:
4条回答
  • 2020-12-09 02:12

    This post was a great help to me. I am always finding new ways to use knockout. I just wanted to add one useful modification which is doing exactly what nemesv proposed only using the ko.mapping plugin.

    //Nested javascript object:
    var formElementNode = {
        children: [{
            children: [],
            text: 'Child1',
            value: 'Value1'
        }, {
            children: [{
                children: [{
                    children: [],
                    text: 'Child2.1.1',
                    value: 'Value2.1.1'
                }],
                text: 'Child2.1',
                value: 'Value2.1'
            }],
            text: 'Child2',
            value: 'Value2'
        }, {
            children: [],
            text: 'Child3',
                value: 'Value3'
        }],
        text: 'Main',
        value: 'MainValue'
    };
    
    //Use ko.mapping to generate viewModel:
    var viewModel = ko.mapping.fromJS(formElementNode);
    ko.applyBindings(viewModel);
    

    As demonstrated in this jsFiddle.

    0 讨论(0)
  • 2020-12-09 02:20

    I think, I have a little better solution with no tree root. Please take a look:

    http://jsfiddle.net/nonsense66/Bzekr/

    Template:

    <script id="treeElement" type="text/html">
        <li>
            <span data-bind="text: name"></span>
            <ul data-bind="template: { name: 'treeElement', foreach: children }">
            </ul>
         </li>
    </script>    
    
    <ul data-bind="template: { name: 'treeElement', foreach: $data.treeRoot }"></ul>
    

    Javascript:

    var viewModel = {
        treeRoot: ko.observableArray()
    };
    
    var TreeElement = function(name, children) {
       var self = this;
       self.children = ko.observableArray(children);
       self.name = ko.observable(name);
    }
    
    var tree = [
        new TreeElement("Russia", [
            new TreeElement("Moscow")
        ]),
        new TreeElement("United States", 
        [
            new TreeElement("New York", [ 
                new TreeElement("Harlem"),
                new TreeElement("Central Park")
            ]) 
        ])
    ];
    
    viewModel.treeRoot(tree);
    
    ko.applyBindings(viewModel);
    

    Hope it helps!

    0 讨论(0)
  • 2020-12-09 02:28

    Recursive Custom Binding

    Another solution, after reading that templates were slower I'm looking at going with recursive binding.

    <ul data-bind="nestMe: name"></ul>

    ko.bindingHandlers.nestMe = {
        init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    
        },
        update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
            var observable = valueAccessor() || { };
            var unwrapped = ko.unwrap(observable);
    
            ko.utils.setHtml(element, '<li>'+unwrapped+'<ul data-bind="foreach: children"><li data-bind="nestMe: name" /></ul></li>');
    
        }
    };
    
    var rootModel = function(name, children) {
        this.name = ko.observable(name);
        this.children = ko.observableArray(children);
    };
    
    var basemodel = new rootModel('test');
    basemodel.children.push(new rootModel('aaa',[new rootModel('111'),new rootModel('222')]));
    basemodel.children.push(new rootModel('bbb'));
    basemodel.children.push(new rootModel('ccc',[new rootModel('333'),new rootModel('444')]));
    
    ko.applyBindings(basemodel);
    

    Having the opportunity to play with data before the recursion should come in handy.

    JSFiddle

    0 讨论(0)
  • 2020-12-09 02:31

    Yes KnockOut supports recursive templates so you can reference and render the same template inside the template.

    An example html in your case would look like this:

    <script id="formElementNodeTemplate" type="text/html">
    <ul>
        <li>Parent <span data-bind="text: text"></span> 
                   <span data-bind="text: value"></span>
            <br/>
            Children:
            <!-- ko template: { name: 'formElementNodeTemplate',  
                                foreach: children } -->
            <!-- /ko -->        
         </li>
       </ul>
    </script>    
    
    <div data-bind="template: { name: 'formElementNodeTemplate', data: $data }">
    </div>
    

    Demo JSFiddle.

    0 讨论(0)
提交回复
热议问题