I have a KO custom binding which adds a component to the page (as a virtual element but i don't think this matters) and then applies a view model to it. The component loads it's template via require from the server.
However during load I am getting a problem where the custom binding is updated and removing the element from the page (I want to have it tidy it's self up if not required).
This results in a race condition - if the asychronous lookup for the template has not finished before the elements are removed when KO tries to apply the component it can't find the closing tag and throws an error.
I am wondering if there is any thing anyone can suggest to alleviate the problem? I already know there is no callback mechanism on applyBindings
and I don't think afterRenderCallback
will help as it errors before it gets that far. I wondered if there is a way to cancel, stop or abort the process and there isn't.
Any ideas?
Here is a fiddle which demonstrates my problem.
My custom binding looks like this:
ko.bindingHandlers.customBinding = {
update: function(element, valueAccessor){
var $element = $(element)
if(ko.unwrap(valueAccessor())){
$element.data("controller", new CustomBindingController(element));
} else {
var controller = $element.data("controller");
if(controller){
controller.destroy();
$element.removeData("controller");
}
}
}
}
It is making calls to a controller class which looks like this:
function CustomBindingController(element){
var self = this,
$element = $(element),
$component;
function init(){
$component = $("<!-- ko component: { name: \"my-component\", params: $data } --><!-- /ko -->");
$("#component-container").append($component);
ko.applyBindings( { message: "Binding Applied!" }, $component[0]);
self.destroy = destroy;
}
function destroy(){
$component.remove();
}
init.call(self);
}
The component is loaded via require:
ko.components.register("my-component", {
//template: "<p data-bind=\"text: message\"></p>"
template: { require: "text!component-template" }
});
And a simplified initialisation looks something like this:
var vm = { shouldBeBound: ko.observable(true) };
ko.applyBindings(vm);
vm.shouldBeBound(false);
In reality I have some more complex dependencies which are setting the flag to false after initialisation has begun.