custom binding will trigger twice

1,109 views
Skip to first unread message

Sxd

unread,
Aug 4, 2011, 1:57:06 AM8/4/11
to KnockoutJS
http://jsfiddle.net/sxd1140/Nvzr3/2/

if i bind two observable to a custom binding
i set one observable ,the update function will be called twice

it's don't make sense

Sxd

unread,
Aug 4, 2011, 1:59:24 AM8/4/11
to KnockoutJS
or we just have bind two custom bindings

Sxd

unread,
Aug 4, 2011, 3:29:49 AM8/4/11
to KnockoutJS
oh,even i bind two different custom bindings,tigger twice still


viewModel.a(); getter will tigger custom bindings?
i thought only setter will tigger.
Message has been deleted

Sxd

unread,
Aug 4, 2011, 4:11:14 AM8/4/11
to KnockoutJS
Message has been deleted

rpn

unread,
Aug 4, 2011, 8:24:56 AM8/4/11
to knock...@googlegroups.com
Hello-
I may not quite understand your question, but in your last fiddle you are doing:

ko.bindingHandlers.cbind1 {
    updatefunction(elementvalueAccessorallBindingsAccessorviewModel{
        var tmp viewModel.b();
        alert(tmp);
    }

};

ko.bindingHandlers.cbind2 {
    updatefunction(elementvalueAccessorallBindingsAccessorviewModel{
        var tmp viewModel.b();
        alert(tmp);
    }

};


These are both hardcoded to access "b".  So, even though you do cbind1: a and cbind2: b, both bindings will still only trigger when "b" is changed.  Bindings are implemented using dependentObservables, so the actual observables that have their value accessed in the binding code will create dependencies.  In this case, only "b" is being accessed.  If you changed it to:

var tmp = ko.utils.unwrapObservable(valueAccessor());

Then, you would propertly bind to "a" in the first and "b' in the second.

Does that help or did I misunderstand your question?

Sxd

unread,
Aug 4, 2011, 8:48:06 AM8/4/11
to KnockoutJS
*cbind1: a*
*cbind2: b*

i just change b,but ko call cbind1.update() and cbind2.update()


why i change b will tigger cbind1.update()?

rpn

unread,
Aug 4, 2011, 8:50:58 AM8/4/11
to knock...@googlegroups.com
All that matters is what is actually accessed in the binding code.  If you do not access what you pass into the binding via the valueAccessor param, then it will not create a dependency.

So, both of your bindings are hardcoded to access "b", which will create a dependency on "b".  You do not access what was passed in via the data-bind attribute, so it will be irrelevant.

Sxd

unread,
Aug 4, 2011, 8:56:03 AM8/4/11
to KnockoutJS
if i need some viewModel's data in update to calculate or somethings

how?

rpn

unread,
Aug 4, 2011, 9:09:10 AM8/4/11
to knock...@googlegroups.com
The idea is that if you access an observable in the update, then if it changes your calculation would be potentially invalid and you would want to run it again.

Do you have a particular scenario in mind?  Maybe we can see what options are available to make it work.  It is possible to create an observable wrapper that provides a backdoor to the actual value as a non-observable, but I would like to understand your situation before suggesting something like that.


Sxd

unread,
Aug 4, 2011, 10:48:05 AM8/4/11
to KnockoutJS
http://jsfiddle.net/sxd1140/VD7J5/5/

my goal is use two datepicker to filter date in datatable

but i set viewModel.filterStartDate(dateText); then custom bindind
have not call update()

btw:http://www.datatables.net/examples/plug-ins/range_filtering.html

can you look it for me

thanks a lot!

rpn

unread,
Aug 4, 2011, 11:19:03 PM8/4/11
to knock...@googlegroups.com
OK- here is what I noticed:
-you set "bFilter: false", looks like you want that to be set to true
-you will want to parse the start and end dates into Date() objects, if they are have a value
-in your comparisons you will probably just want to do !start and !end instead of checking against "", unless you set it to "", if it is empty

Seems to work after that.  Also, here is a link to a datepicker binding that will read/write Date objects directly: http://jsfiddle.net/rniemeyer/NAgNV/

Sxd

unread,
Aug 4, 2011, 11:35:46 PM8/4/11
to KnockoutJS
thanks for response!

in my fiddle, when i click datepicker alert("dateSelected") so will
viewModel.filterStartDate(dateText);

but have not call OnStartChange.update(),have not
alert("StartChanged")

"StartChanged" and "EndChanged" just show on init()

so my problem is why don't call update() even i change model

rpn

unread,
Aug 5, 2011, 12:02:47 AM8/5/11
to knock...@googlegroups.com
The problem that you are seeing is that your update functions do not access any observables, so they have no dependencies.  The update function will only run again if an observable that it depends on is changed.  If you need to, you can simply access the appropriate observable in your binding.

rwIII

unread,
Aug 5, 2011, 12:35:48 AM8/5/11
to knock...@googlegroups.com
Hi rpn, i am having a problem where my bindingHandlers are being called twice as well!

I've got something like this:

ko.bindingHandlers.chooseGender = {
    init: function (element, valueAccessor) {
        $('<span class="male">male</span>').appendTo(element);
        $('<span class="female">female</span>').appendTo(element);
        $('<span class="other">other</span>').appendTo(element);
    }
};


var signUpModel;

    $(document).ready(function () {
        signUpModel = new SignUpModel();
        ko.applyBindings(signUpModel);
    });

    function SignUpModel() {
        this.userID = ko.observable("");
        this.userName = ko.observable("");
        this.fullName = ko.observable("");
        this.emailAddress = ko.observable("");
        this.password = ko.observable("");
        this.gender = ko.observable("");
        this.dateOfBirth = ko.observable("");
        this.profileImage = ko.observable("");
        this.levelID = 1;
    }

<div class="fieldContainer">
            <div class="inputContainer" data-bind="chooseGender:signUpModel.gender">
            </div>
            <p class="inputHelp inputTip">
                Not required</p>
        </div>


The result is:

<span class="male">male</span>
<span class="female">female</span>
<span class="other">other</span>
<span class="male">male</span>
<span class="female">female</span>
<span class="other">other</span>

rpn

unread,
Aug 5, 2011, 12:42:25 AM8/5/11
to knock...@googlegroups.com
You are not calling applyBindings more than once are you?

Otherwise, I don't see why it is firing twice.  There must be more going on, as it does not fire twice here: http://jsfiddle.net/rniemeyer/ttgCY/

rwIII

unread,
Aug 5, 2011, 1:02:37 AM8/5/11
to knock...@googlegroups.com
yeah.. strange. I just ran a jsfiddle and same thing. I am calling applyBindings twice but not with the same viewmodel. I have a sort of persistant bar with a sign-in model running on all pages.. Would this do it even though i am passing a different viewmodel?
Message has been deleted
Message has been deleted

Sxd

unread,
Aug 5, 2011, 3:11:14 AM8/5/11
to KnockoutJS
ok thanks.
write var value = ko.utils.unwrapObservable(valueAccessor()); in
update() then update() will be called even i don't use that
Reply all
Reply to author
Forward
0 new messages