Matthew The Terrible
Matthew The Terrible

Reputation: 1643

knockoutjs get count of items that meet a condition

I have a view model that has an observable array in it which inside has an observable array. I want to keep track when users check items off their lists. I have the following view model and html:

var mydata = {
        Incomplete: ko.computed(function () {
           // return the count of items that are not IsActive
        }),
        Categories: ko.observable([
              {
                  Description: "Dairy", ListItems: ko.observableArray([
                  { Description: "Eggs", Quantity: "1 Dz.", IsActive: ko.observable(false) },
                   { Description: "Milk", Quantity: "1 Gallon", IsActive: ko.observable(false) }
                  ])
              },
              {
                  Description: "Produce", ListItems: ko.observableArray([
                      { Description: "Lettuce", Quantity: "1 Head", IsActive: ko.observable(false) },
                      { Description: "Oranges", Quantity: "5 ea.", IsActive: ko.observable(false) },
                      { Description: "Greenbeans", Quantity: "1 Thingy", IsActive: ko.observable(false) },
                  ])
              },
        ])
    };

<div data-bind="foreach: Categories" id="list-items">
            <h3 data-bind="text: Description" id="list-heading"></h3>
            <ul data-bind="foreach: ListItems">
                <li>
                    <div class="title">
                        <input type="checkbox" data-bind="checked: IsActive"/>
                        <input type="text" data-bind="value: Quantity, disable: IsActive" class="input-readonly" readonly />
                        <input type="text" data-bind="value: Description, disable: IsActive" class="input-readonly" readonly />
                    </div>
                </li>
            </ul>
        </div>
        <div >
            <span data-bind="text: Incomplete"></span>
            <span >Items left in your list</span>
        </div>

Upvotes: 3

Views: 2501

Answers (1)

RP Niemeyer
RP Niemeyer

Reputation: 114792

With your current code, you would want to loop through the categories and then for each category loop through the individual items. Here is one possible implementation:

Incomplete: ko.computed(function () {
    var count = 0;
    ko.utils.arrayForEach(mydata.Categories(), function(category) {
        ko.utils.arrayForEach(category.ListItems(), function(item) {
             if (!item.IsActive()) {
                  count++;
             }
        });
    });

    return count;
}),

Upvotes: 5

Related Questions