Knockout works not as I expected

101 views
Skip to first unread message

Nikolay Sonin

unread,
Oct 7, 2016, 4:48:16 PM10/7/16
to KnockoutJS
HTML:

        <div id="ctlAlert" class="alert error-message">
            <ul id="ctlAlertUL" data-bind="foreach: allErrors">
                <li data-bind="text: $data" class="text-danger"></li>
            </ul>
        </div>

<button id="btnErr1">Err1</button>
<button id="btnErr2">No ERR</button>


Enter code here    <script>


        $(document).ready(function () {

var ErrorsListModel = function (items) {
        var self = this;
        self.allErrors = ko.observableArray(items);
        self.hasErrors = ko.computed(function () {
            return self.allErrors().length > 0;
        });
    }

    
    $("#btnErr1").click(function (evt)
    {
ko.cleanNode($("#ctlAlertUL")[0]);
      var rt = '["msg1", "msg2"]';
      var ve = $.parseJSON(rt);
      ko.applyBindings(new ErrorsListModel(ve), $("#ctlAlertUL")[0]);
    });


    $("#btnErr2").click(function (evt)
    {
ko.cleanNode($("#ctlAlertUL")[0]);
      var rt = '[]';
      var ve = $.parseJSON(rt);
      ko.applyBindings(new ErrorsListModel(ve), $("#ctlAlertUL")[0]);
    });

});

    </script>
...

1. When I click many times on Err1 I see MSG multiplied twice upon each click
2. When I click on NoERR I have ctlAlertUL clean, but when I click on Err1 after that I see no new MSG added

This makes me frustrating. What I'm doing wrong ?

Gunnar Liljas

unread,
Oct 8, 2016, 10:50:45 AM10/8/16
to knock...@googlegroups.com
As a general rule, applyBindings should be called exactly once. CleanNode doesn't remove the results of the bindings, it just removes the bindings, so when you do it like this, you're effectively changing the foreach template everytime you click.

Change the contents of the allErrors array instead of creating a new ErrorListModel and rebinding. 

/G


Nikolay Sonin

unread,
Oct 9, 2016, 2:53:07 PM10/9/16
to KnockoutJS
Ok, I removed CleanNode() but now I'm getting "You cannot apply bindings multiple times to the same element" msg in Chrome dev log every time after the very first click on Err1. What I'm doing wrong now?

Gunnar Liljas

unread,
Oct 9, 2016, 5:00:45 PM10/9/16
to knock...@googlegroups.com
As I wrote, applyBindings should be called exactly once. You are calling it repeatedly. What you need is something like this (in concept).

var ErrorsListModel = function (items) {
        var self = this;
        self.allErrors = ko.observableArray(items);
        self.hasErrors = ko.computed(function () {
            return self.allErrors().length > 0;
        });
}

var vm=new ErrorsListModel([]);

   $(document).ready(function () {


        ko.applyBindings(vm, $("#ctlAlertUL")[0]);
    }

    
    $("#btnErr1").click(function (evt)
    {
      vm.allErrors(["msg1", "msg2"]);
    });


    $("#btnErr2").click(function (evt)
    {
      vm.allErrors([]);
    });

});


--
You received this message because you are subscribed to the Google Groups "KnockoutJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to knockoutjs+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages