knockout js 'with' binding, hide if array is empty
Asked Answered
O

1

8

I have a category drop down list which controls a sub category drop down list. I want to hide the sub categories drop down list if the sub category array is empty for the selected category.

Sample code below:

<script>

    self.categories = ko.observableArray([
            {"name": "top 1", "subcategories":[
                                              {"name": "sub 1"},
                                              {"name": "sub 2"}
                                              ]},
            {"name": "top 2", "subcategories":[]}
    ]);

    self.selected_category = ko.observable();
    self.selected_sub_category = ko.obserable();

</script>

<div>
    <select data-bind="options: categories, optionsText: "name", optionsCaption: "Select", value: selected_category"></select>
</div>  
<div data-bind="with:selected_category">
    <select data-bind="options: subcategories, optionsText: "name", optionsCaption: "Select", value: selected_sub_category"></select>
</div>  

Officiary answered 14/4, 2013 at 15:9 Comment(0)
A
11

You need to combine the with binding with the if (or the visible) binding where you can specify your condition:

<div data-bind="with: selected_category">
    <!-- ko if: subcategories.length > 0 -->
    <select data-bind="options: subcategories, optionsText: 'name', 
        optionsCaption: 'Select', value: $parent.selected_sub_category"></select>
    <!-- /ko -->
</div> 

Demo JSFiddle.

Note the usage of the $parent in the value: $parent.selected_sub_category, you need that to access "parent" object because the with creates a child context.

If you don't want to render the whole div when the sub collection is empty then you need to move the with and if outside your div because KO not allow to use multiple control-flow bindings on the same element.

So in that case your HTML would look like this:

<!-- ko with:selected_category -->
    <!-- ko if: subcategories.length > 0 -->
        <div class="mydiv">    
            <select data-bind="options: subcategories, optionsText: 'name', 
                    optionsCaption: 'Select', 
                    value: $parent.selected_sub_category">
            </select>    
        </div> 
    <!-- /ko -->
<!-- /ko -->

Demo JSFiddle.

Agglomeration answered 14/4, 2013 at 15:46 Comment(2)
Thanks nemesv. Is there a way to combine the with and if into the one data-bind attribute. The reason is that I would prefer it if the div was not rendered at all.Officiary
The if and with cannot be combined in on data-bind attribute. If you try it you will get the following error message: "Multiple bindings (with and if) are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element." But you move them "outside" see my updated answer.Agglomeration

© 2022 - 2024 — McMap. All rights reserved.