Rekursives Template mit Knockout js

Lesezeit: 4 Minuten

Benutzer-Avatar
Benzy

Ist es möglich, eine rekursive Vorlage nur mit Knockout js zu erstellen?

Ich habe ein Knockout-Objekt:

function FormElementNode(children, text, value) {
   var self = this;
   self.children = ko.observableArray(children);
   self.text = ko.observable(text);
   self.value = ko.observable(value);
}   

children ist ein Array von FormElementNode.

Ich möchte es und seine Kinder rekursiv in einer Hierarchieliste mit Knoten zeichnen:

<ul>
   <li>Parent text value:
      Children: 
      <ul>
         <li>Child1 text value</li>
         <li>Child2 text value</li>
   </li>

Vielen Dank!

Ja, KnockOut unterstützt rekursive Vorlagen, sodass Sie dieselbe Vorlage innerhalb der Vorlage referenzieren und rendern können.

Ein Beispiel-HTML würde in Ihrem Fall so aussehen:

<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.

  • Danke für die schnelle Antwort. Ich habe ein weiteres ‘foreach’ in der Vorlage – und ich erhalte eine Fehlermeldung: “Diese Vorlagen-Engine unterstützt die ‘foreach’-Bindung in ihren Vorlagen nicht”. Sollte ich eine andere Vorlage verwenden, um dieses verschachtelte foreach zu erstellen?

    – Benzy

    20. März 2013 um 14:44 Uhr

  • Ein weiteres Problem ist, dass ich möchte, dass die Kinder Geschwister sind, die durch

  • dargestellt werden. Die von Ihnen angebotene aktuelle Lösung öffnet für jedes Kind eine neue Liste (
      ).

      – Benzy

      20. März 2013 um 14:44 Uhr

  • In Bezug auf Ihre Antother foreach Problem: Ich denke, Sie sollten es in einer anderen Frage stellen, in der Sie Ihren tatsächlichen problematischen Code zeigen. Über die <ul> Ich habe gerade ein kleines Beispiel zur Verfügung gestellt, wenn Sie bestimmte Bedürfnisse haben, können Sie damit spielen, wo Sie Ihre setzen ul, li rund um Ihre Vorlage: jsfiddle.net/KtbXb/1

    – nemesv

    20. März 2013 um 14:57 Uhr


  • Vielen Dank! Es funktioniert jetzt! Bezüglich der foreach Problem, als ich den Unterstrich entfernt habe, war der Fehler weg 🙂

    – Benzy

    20. März 2013 um 15:50 Uhr

  • @nemesv Tolle Antwort. Wie aktualisieren Sie den Code, damit ein Benutzer zur Laufzeit Elemente zu untergeordneten Elementen hinzufügen kann? Haben Sie zum Beispiel eine Schaltfläche, auf die er / sie klicken kann, und ein neues Element wird hinzugefügt. Ich kann es für die Wurzel bekommen, aber nicht für Kinder?

    – Phil

    14. Juli 2013 um 17:34 Uhr

  • Benutzer-Avatar
    Andrej

    Ich glaube, ich habe ein bisschen bessere Lösung mit keine Baumwurzel (oder ich vermute mehrere Baumwurzeln). Bitte schau es dir an:

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

    Schablone:

    <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);
    

    Ich hoffe es hilft!

    Dieser Beitrag war mir eine große Hilfe. Ich finde immer neue Wege, Knockout einzusetzen. Ich wollte nur eine nützliche Modifikation hinzufügen, die genau das tut, was nemesv vorgeschlagen hat, nur mit dem 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);
    

    Wie hier gezeigt jsFiddle.

    Rekursive benutzerdefinierte Bindung

    Eine andere Lösung, nachdem ich gelesen habe, dass Vorlagen langsamer sind, überlege ich, mit rekursiver Bindung zu gehen.

    <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);
    

    Die Möglichkeit zu haben, vor der Rekursion mit Daten zu spielen, sollte sich als nützlich erweisen.

    JSFiddle

    1137350cookie-checkRekursives Template mit Knockout js

    This website is using cookies to improve the user-friendliness. You agree by using the website further.

    Privacy policy