I would like to build a custom bindingHandler
ko.bindingHandlers.foreachWithHighlight that has an highlight effect when afterAdd.
From documentation
<
I've modified one of the knockout tutorials, it doesn't use a custom binding though but still drives the behaviour via beforeRemove
and afterAdd
which hook into the observableArray.
data-bind='template: {
foreach: planetsToShow,
beforeRemove: hidePlanetElement,
afterAdd: showPlanetElement
}'
Depending on compatibility you could use css3 transitions as I've done here to give the newly added element a yellow colour that transitions to the normal one after a given timing. (Although the timings and colourings I used need work ;))
In this fiddle it seems to be working by not applying to the original list, but I guess this might be down to at what stage the observableArray gets modified?
http://jsfiddle.net/8k8V5/1529/
If I understand your scenario correctly, then the issue is that the initial time that you populate your observableArray (after binding) you see your highlight. One way to handle a scenario like this would be to use ko.utils.domData
or $.data
to put a flag on the element to indicate that it is now ready for the highlight effect.
Something like:
ko.bindingHandlers.foreachWithHighlight = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, context);
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
var value = ko.unwrap(valueAccessor()),
key = "forEachWithHightlight_initialized";
var newValue = function () {
return {
data: value,
afterAdd: function (el, index, data) {
if (ko.utils.domData.get(element, key)) {
$(el).filter("li")
.animate({
backgroundColor: 'yellow'
}, 200)
.animate({
backgroundColor: 'white'
}, 800);
}
}
};
};
ko.bindingHandlers.foreach.update(element, newValue, allBindingsAccessor, viewModel, context);
//if we have not previously marked this as initialized and there are currently items in the array, then cache on the element that it has been initialized
if (!ko.utils.domData.get(element, key) && value.length) {
ko.utils.domData.set(element, key, true);
}
return { controlsDescendantBindings: true };
}
};
Fiddle here: http://jsfiddle.net/rniemeyer/zGJX3/