Reputation: 480
I would like to know how I can force a knockout binding to refresh it's value. Normally we use an observable and that way the binding can happen automatically when the observable changes. But in my case I have created a custom binding:
if (!ko.bindingHandlers.asyncHtml) {
ko.bindingHandlers.asyncHtml = {
init: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
var parameters = value.params.concat([function (data) {
$(element).html(data);
} ]);
parameters.concat([function (data) {
$(element).html('Unable to retrieve html.');
} ]);
value.source.apply(null, parameters);
}
}
}
This is so that a function which performs an asynchronous JSON call can update the respective element (with the returned HTML) once the call completes. The element, a DIV in this case, looks like this:
<div id="myDiv" data-bind="asyncHtml: {source: getHtml, params: [myId()]}">
My problem is that, another feature on this page can change database values that require myDiv to be updated as a result. I can probably find a complicated way to correct this problem but I was wondering if there was a simpler way where I can just force the binding to reapply?
NOTE: getHtml is a function on my viewmodel which performs the JSON call to retrieve the HTML.
Thanks
Upvotes: 3
Views: 8630
Reputation: 1061
I hope I understood what you are trying to accomplish correctly, but I am not sure, so let me explain how I understand your objective.
You have an ajax function (getHtml) which retrieves this html and onSuccess updates #myDiv, possibly with this:
$('#myDiv').html(serverResponseHTMLContent);
You then have another function which may produce different HTML that should take the place of the server generated html.
If this is all correct then I would suggest you use knockout's html binding.
Your div would look like so.
<div id="myDiv" data-bind="html: myDivInnerHtml">
myDivInnerHtml would be part of your viewModel and should be an observable as you say you usually do. Before the initial bind, call getHtml and have it set the value for myDivInnerHtml instead of actually setting the html for myDiv.
myDivInnerHtml = ko.observable(serverHtmlString);
Then when you apply the binding, myDiv's inner Html will be set by knockout. To update the html, your client side function can change the value of myDivInnerHtml.
myDivInnerHtml(clientSideFunctionHtmlString);
If my assumptions are wrong and you have recreate the same html with different value, then you should use a template if possible and the server should not be sending the html, but instead the values to bind to the html.
Also, if the client side function is not creating html, but instead values to be bound to the html, then this will also not work.
Upvotes: 3
Reputation: 13278
You could look at the valueHasMutated()
function which notifies subscribers that they should re-evaluate the observable.
See How to force a view refresh without having it trigger automatically from an observable? for a bit more explanation.
Upvotes: 2