I'm using "with" binding and I would like to invoke some animation before change value, and after that. Does any body know how to do it?
问题:
回答1:
You could always wrap the with binding with your own binding which uses jQuery for some animation like so:
ko.bindingHandlers['fadingWith'] = {
init: function(element, valueAccessor, allBindingsAccessor, context) {
return ko.bindingHandlers['with']['init'](element, valueAccessor, allBindingsAccessor, context);
},
update: function(element, valueAccessor, allBindingsAccessor, context) {
$(element).fadeOut(100, function () {
ko.bindingHandlers['with']['update'](element, valueAccessor, allBindingsAccessor, context)
}).fadeIn(100);
}
};
ko.virtualElements.allowedBindings['fadingWith'] = true;
Then you can apply it like so: <div data-bind="fadingWith: someObservable"><span data-bind="text: $data"></span></div>
I haven't tested this (I will try it out later), but I would think this would be the direction to go.
Another option (which I am more sure would work) is that you create a separate binding that does the following:
ko.bindingHandlers['fadeOn'] = {
update: function(element) {
$(element).hide().fadeIn(200);
}
}
That doesn't give you the animation for before the observable changes, but it would give you an animation afterwards. So you would do <div data-bind="with: someObservable, fadeOn: someObservable"><span data-bind="text: $data"></span></div>
EDIT: Another possibly easier option I came up with just now is to use the throttle extension on the variable you are using with
with:
ViewModel:
///...your code....
this.observableThatNeedsWith = ko.observable("Hello");
this.delayedObservable = ko.computed(this.observableThatNeedsWith).extend({throttle: 200});
//...continue your code
Then, you have a binding as follows:
ko.bindingHandlers['fadeInOut'] = {
update: function(element) {
$(element).stop(true, true).stop(true, true).fadeOut(200).fadeIn(200);
}
}
Notice that the fade-out time is the same as the throttle time.
Then you bind it like so: <div data-bind="with: delayedObservable, fadeInOut: observableThatNeedsWith"><span data-bind="text: $data"></span></div>
What will happen is that when you change the observableThatNeedsWith, the fadeInOut handler will begin transitioning the element. Then at the moment that it gets done fading out (200ms in this case) the throttle will catch up and the delayedObservable will update right as fadeInOut begins fading the element back in. It fades out one thing, and fades in another.
回答2:
I'm resolved problem by creating binding that create copy of the element. After clone this element I animate it and after that I'm delete it and animate orginal element with new values. It is important to set this binding before with
回答3:
Los Frijoles 3rd solution won't work since it will throttle the 'with' binding to always take place after the animation.
Since we are attempting to animate the elements rendered by the with binding, when going from an unrendered state to a rendered state, the animation will attempt to animate elements that don't exist.
Slawomir's answer is the best I've seen, but cloning complex elements when animating on mobile devices isn't an option for performance reasons. Properly implementing animations for these bindings requires improvements to the Knockout framework.
Edit: I've realized that it's possible to animate a 'with' or 'if' binding by replacing it with an 'template' or 'foreach' tag of equivalent logic. For example, I replaced:
<div data-bind="with: selectedTimelapse">
with:
<div data-bind="template: {
foreach: selectedTimelapse,
afterAdd: utils.kbAnimFadeIn,
beforeRemove: utils.kbAnimFadeOut
}">
There's no need for 'selectedTimelapse' from my example to be a list. Using this I can now transition in and out my modal dialog when selectedTimelapse is set. This technique can be hacked to work for if transitions as well:
<div data-bind="template: {
foreach: (showTimelapse()) ? selectedTimelapse : undefined,
afterAdd: utils.kbAnimFadeIn,
beforeRemove: utils.kbAnimFadeOut
}">
My utils.kbAnimFadeIn/Out functions are equivalent to the functions demonstrated in the Knockout animation example page here: http://knockoutjs.com/examples/animatedTransitions.html