Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
async *wrapper* binding
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  9 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Michael Best  
View profile  
 More options Nov 30 2011, 8:14 pm
From: Michael Best <mb...@dasya.com>
Date: Wed, 30 Nov 2011 17:14:19 -0800 (PST)
Local: Wed, Nov 30 2011 8:14 pm
Subject: async *wrapper* binding
The normal behavior in Knockout is for all bindings on an element to
be linked together. Their dependencies are combined so that an update
to any of the observables in the bindings will update all the
bindings.

This can be a performance issue because updating some bindings is
relatively expensive (options, template). Take following example from
an application I'm developing:

    <!-- ko foreach: navigation.pages -->
    <div class="body row scroll-y" data-bind="
            visible: isCurrent,
            attr: { id: 'content' + id },
            template: { name: id, 'if': isLoaded, afterRender:
afterRender }">
    </div>
    <!-- /ko -->

The current page will have isCurrent == true, while all others will
have isCurrent == false. With the above code, whenever the current
page changes, the template is also re-rendered. My initial solution
was to wrap the div in another and move the 'visible' binding to the
outer div:

    <!-- ko foreach: navigation.pages -->
    <div data-bind="visible: isCurrent">
        <div class="body row scroll-y" data-bind="
                attr: { id: 'content' + id },
                template: { name: id, 'if': isLoaded, afterRender:
afterRender }">
        </div>
    </div>
    <!-- /ko -->

But now with the async wrapper binding (see below), I can make it a
single div again:

    <!-- ko foreach: navigation.pages -->
    <div class="body row scroll-y" data-bind="
            async: { visible: isCurrent },
            attr: { id: 'content' + id },
            template: { name: id, 'if': isLoaded, afterRender:
afterRender }">
    </div>
    <!-- /ko -->

The async wrapper binding can be used to isolate bindings that modify
a property of an element and are likely to be updated dynamically,
such as visible, enable, and hasfocus, from bindings that are used to
generate content, such as template, html, and options. See
http://groups.google.com/group/knockoutjs/browse_thread/thread/d58dc5...
about using this with 'options'.

Here is the source for the binding:

ko.bindingHandlers['async'] = {
    'init': function(node, valueAccessor, parsedBindingsAccessor,
viewModel, bindingContextInstance) {
        var parsedBindings = valueAccessor();
        function makeValueAccessor(bindingKey) {
            return function () { return parsedBindings[bindingKey] }
        }
        var binding, bindingKey;
        for (bindingKey in parsedBindings) {
            if (!(binding = ko.bindingHandlers[bindingKey])) {
                continue;
            }
            if (!ko.isObservable(parsedBindings[bindingKey])) {
                throw new Error('async binding must be used with
observables only');
            }
            ko.dependentObservable((function(bindingKey, binding){
                var isInit = false;
                return function () {
                    if (!isInit && typeof binding["init"] ==
"function") {
                        var initResult = binding["init"](node,
makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel,
bindingContextInstance);
                        isInit = true;
                    }
                    if (typeof binding["update"] == "function") {
                        binding["update"](node,
makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel,
bindingContextInstance);
                    }
                }
            })(bindingKey, binding), null,
{'disposeWhenNodeIsRemoved': node});
        }
    }


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Mark Bradley  
View profile  
 More options Nov 30 2011, 9:53 pm
From: Mark Bradley <barkmad...@gmail.com>
Date: Thu, 1 Dec 2011 13:53:02 +1100
Local: Wed, Nov 30 2011 9:53 pm
Subject: Re: async *wrapper* binding
I think it might be important to note that if your binding definition
dereferences the observable directly [1] then the async binding will
not work as expected.  Not a deal breaker, but a caveat worth
mentioning.

[1]: e.g.

<tag data-bind="text: observableA, async: { visible: observableB() ||
false }"></tag>

The text binding will be evaluated whenever observableB is updated
because as it is processed currently, the observableB will be a
dependency of the whole DO, not the async DO.

--
-barkmadley
sent from an internet enabled device
http://barkmadley.com

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Michael Best  
View profile  
 More options Dec 1 2011, 8:31 am
From: Michael Best <mb...@dasya.com>
Date: Thu, 1 Dec 2011 05:31:31 -0800 (PST)
Local: Thurs, Dec 1 2011 8:31 am
Subject: Re: async *wrapper* binding
Mark,

Yeah, there's no easy way around that. I have this in my code to check
that you're binding to an observable:

if (!ko.isObservable(parsedBindings[bindingKey])) {
    throw new Error('async binding must be used with observables
only');

}

Of course, this does prevent some bindings that would actually be
okay, so I'm not sure about leaving it there or not.  For example:

<tag data-bind="text: observableA, async: { css: { 'classname':
observableB } }"></tag>

would fail the observable check.

-- Michael

On Nov 30, 4:53 pm, Mark Bradley <barkmad...@gmail.com> wrote:


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
rpn  
View profile  
 More options Dec 1 2011, 9:22 am
From: rpn <rnieme...@gmail.com>
Date: Thu, 1 Dec 2011 06:22:17 -0800 (PST)
Local: Thurs, Dec 1 2011 9:22 am
Subject: Re: async *wrapper* binding

A generic binding for this is a nice idea Michael!


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Michael Best  
View profile  
 More options Dec 1 2011, 2:50 pm
From: Michael Best <mb...@dasya.com>
Date: Thu, 1 Dec 2011 11:50:45 -0800 (PST)
Local: Thurs, Dec 1 2011 2:50 pm
Subject: Re: async *wrapper* binding
Great! I posted it to the wiki: https://github.com/SteveSanderson/knockout/wiki/Bindings---async

On Dec 1, 4:22 am, rpn <rnieme...@gmail.com> wrote:


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Michael Best  
View profile  
 More options Dec 1 2011, 3:12 pm
From: Michael Best <mb...@dasya.com>
Date: Thu, 1 Dec 2011 12:12:57 -0800 (PST)
Local: Thurs, Dec 1 2011 3:12 pm
Subject: Re: async *wrapper* binding
Another way to use this binding is to create a new binding using this
function:

    var createAsyncBinding = function(binding, newname) {
        if (typeof newname == 'undefined') {
            newname = binding + 'Async';
        }
        var makeAsyncValueAccessor = function(valueAccessor) {
            return function() { var r = {}; r[binding] =
valueAccessor(); return r; };
        };
        ko.bindingHandlers[newname] = {
            'init' : function(node, valueAccessor,
parsedBindingsAccessor, viewModel, bindingContextInstance) {
                return ko.bindingHandlers['async']['init'](node,
makeAsyncValueAccessor(valueAccessor),
                    parsedBindingsAccessor, viewModel,
bindingContextInstance);
            }
        }
    };

Calling the function will create a new binding:

    createAsyncBinding('visible');    // will create a visibleAsync
binding

Now the above example can be redone as:

    <!-- ko foreach: navigation.pages -->
    <div class="body row scroll-y" data-bind="
            visibleAsync: isCurrent,
            attr: { id: 'content' + id },
            template: { name: id, 'if': isLoaded, afterRender:
afterRender }">
    </div>
    <!-- /ko -->


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
lovedota  
View profile  
 More options Dec 1 2011, 9:08 pm
From: lovedota <lovedot...@gmail.com>
Date: Thu, 1 Dec 2011 18:08:14 -0800 (PST)
Local: Thurs, Dec 1 2011 9:08 pm
Subject: Re: async *wrapper* binding
Could you please post a demo in jsfiddler ! Thanks !

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
lovedota  
View profile  
 More options Dec 1 2011, 9:23 pm
From: lovedota <lovedot...@gmail.com>
Date: Thu, 1 Dec 2011 18:23:06 -0800 (PST)
Local: Thurs, Dec 1 2011 9:23 pm
Subject: Re: async *wrapper* binding
<!-- ko foreach: navigation.pages -->
<div class="body row scroll-y" data-bind="
        async: { visible: isCurrent },
        attr: { id: 'content' + id },
        template: { name: id, 'if': isLoaded, afterRender:
afterRender }">
</div>
<!-- /ko -->

Could you please give this in the fiddler !  Thanks !


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Mark Bradley  
View profile  
 More options Dec 2 2011, 12:36 am
From: Mark Bradley <barkmad...@gmail.com>
Date: Fri, 2 Dec 2011 16:36:23 +1100
Local: Fri, Dec 2 2011 12:36 am
Subject: Re: async *wrapper* binding
After the 1.3 release it would be worth investigating the possibility
of making the binding's as lazy as possible.

I know each binding handler takes a function that will return the
value of it's key-value pair.  However this function is created much
too late in the process, as such bindings get "evaluated" and then the
values get wrapped in functions (or not if they are observables, or
something).  It would be really great if we could combine the two
different bits of code:

https://github.com/SteveSanderson/knockout/blob/master/src/binding/js...

with a transformation that makes it look like this bit of code:

https://github.com/SteveSanderson/knockout/blob/master/src/utils.js#L169

such that this:

'visible: observable'

gets converted into this:

'{ visible: function() { return ( with(sc[0]) { observable; } ); } }'

instead of this:

'(function(sc) { return ( with(sc[0]) { { visible: observable }; } );

})(scopes)'

(I know this isn't exactly a correct characterisations of how knockout
works, however the concept is sound).

On Fri, Dec 2, 2011 at 1:22 AM, rpn <rnieme...@gmail.com> wrote:
> A generic binding for this is a nice idea Michael!

--
-barkmadley
sent from an internet enabled device
http://barkmadley.com

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »