Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout observableArray not updating

Tags:

knockout.js

I have an observableArray that won't update in the HTML even though I can log it to the console and see it change.

The example below has a list of people (people). I search that list and try to add the results to a new observableArray (searchResult) that is bound to an unordered list. This list element is never updated, though the console shows that the correct entries from people are found. Why aren't the search results showing in the HTML?

Here is my code (also available on JSFiddle):

    function AppViewModel() {
        var self = this;

        self.people = ko.observableArray([{
            fName: "Thomas",
            lName: "Edison"
        }, {
            fName: "Sally",
            lName: "Salputrio"
        }, {
            fName: "Edward",
            lName: "Sparkleshine"
        }, {
            fName: "Jacob",
            lName: "Wolfsson"
        }]);
        self.searchResult = ko.observableArray([]);
        self.searchFieldKo = ko.observable("");

        self.submitSearch = function () {
            if (self.searchFieldKo() != "") {
                self.searchResult().length = 0;
                $.each(self.people(), function (pKey, pObj) {
                    $.each(pObj, function (pProp, pValue) {
                        if (pValue.toString().toLowerCase().indexOf(self.searchFieldKo().toLowerCase()) >= 0) {
                            self.searchResult().push(self.people()[pKey]);
                            console.log(self.searchResult());
                        }
                    })
                })
            } else {
                alert("Please type something.");
            }
        }
    }

    ko.applyBindings(new AppViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
<fieldset class="span20 offset2">
    <legend>Search Me!</legend>
    <form class="form-search">
        <div class="input-append">
            <input type="text" data-bind="value: searchFieldKo, valueUpdate: 'afterkeydown'" class="input-medium search-query" id="searchField">
            <button class="btn" data-bind="click: submitSearch">search</button>
        </div>
    </form>
     <h5> Search Results:</h5>

    <ul data-bind="foreach: searchResult" class="unstyled">
        <li> <span data-bind="text: fName"></span>  <span data-bind="text: lName"></span>

        </li>
    </ul>
     <h5>People List:</h5>

    <ul data-bind="foreach: people" class="unstyled">
        <li> <span data-bind="text: fName"></span>  <span data-bind="text: lName"></span>

        </li>
    </ul>
</fieldset>
like image 948
Tom Avatar asked Dec 01 '25 06:12

Tom


1 Answers

You have an unnecessary set of parenthesis in

self.searchResult().push(self.people()[pKey]); 

it should be

self.searchResult.push(self.people()[pKey]);

Demo JSFiddle.

Because when you write self.searchResult() you are accessing the underlaying array in the observable. And when you push into that array KO won't be notified about the changes so you need to use the push method on the observableArray itself.

By the way Knockout has a great set of useful array helpers which could simplify your filtering logic.

like image 165
nemesv Avatar answered Dec 04 '25 12:12

nemesv



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!