Search code examples
javascriptarraysobjectknockout-2.0knockout-3.0

bind to filtered object property knockout nested foreach


I am trying to understand $parent, $data and stuck trying to filter out object array based on the $parent value.

<p>My kids:</p>
    <ul data-bind="foreach: kids">
        <li> <span data-bind="text: $data" ></span>      
              <ul data-bind="foreach: grandKids.filter(function (obj) { return obj.mother === $parent })">
                 <li><span data-bind="text: $data.name"></span></li>                      
             </ul>
         </li>
      </ul>


    <script src="Scripts/knockout-3.4.1.js"></script>
    <script>
        var vm = {
            name : ko.observable("Anjan"),
            age: ko.observable(40),
            kids: ["Mira", "Teresa"],
            grandKids: [
                         { name: "Andy", mother: "Mira" }, 
                         { name: "Alice", mother: "Mira" }, 
                         { name: "Alex", mother: "Teresa" }, 
                         { name: "Abby", mother: "Teresa" }
                       ]
        };

Solution

  • For anyone, who ran into this kind of issue binding an element into a filtered set, I am sure there are other ways of doing it to, but the way i resolved this was by using a container-less KO binding, as below:

    <ul data-bind="foreach: kids">
                    <li>                         
                        <span data-bind="text: $data.name" > </span>  
                         <button data-bind="click: $parent.removeKid">Remove (moved out)</button> 
                         <button data-bind="click: $root.addGrandKid" style="float:right;">Just had a baby</button>
    
                        <ul data-bind="foreach: vm.grandKids">
                            <!--ko if: $parent.name() == $data.mother() -->
                                <li>                    
                                    <!--ko $data.name() --><!-- /ko -->
    
                                </li>  
                            <!-- /ko-->                    
                        </ul> 
    
                      </li>            
                </ul>
    

    I am still unclear as to why I needed to fully qualify the grandKids property as vm.grandKids in the UI binding for the unordered list.