I have finally found the time to start learning KnockoutJS while building a new MVC4 application. I am trying to figure out the best way to initialize an observable value from a default value that is already set in the view.
This is a contrived example, but I would like to render out a default value for an observable directly to the view as follows:
<input type="hidden"
value="@Model.SomeValue"
data-bind="value: myObservableReference"/>
I know that a default value is normally initialized via:
model.myObservableReference = ko.obervable("SomeValue");
However, I would like to find a way to extend the initialization such that:
model.myObservableReference = ko.obervable();
would read the existing value from the binding if a value exists.
As I have so far managed to keep my KnockoutJS code completely unaware of the razor world, I want to to avoid the sloppiness of:
model.myObservableReference = ko.obervable(@Model.SomeValue);
I am guessing this would be handled via either an extender or custom binder, but if someone could point me in the right direction it would be greatly appreciated.
You could try creating your own custom binding handler to achieve this:
ko.bindingHandlers.initializeValue = {
init: function(element, valueAccessor) {
valueAccessor()(element.getAttribute('value'));
},
update: function(element, valueAccessor) {
var value = valueAccessor();
element.setAttribute('value', ko.utils.unwrapObservable(value))
}
};
<input type="hidden" value="@Model.SomeValue"
data-bind="initializeValue:myObservableReference, value: myObservableReference"/>
For you googlers out there, here is the code to extend the initializeValue binding to a select box as well as input boxes
ko.bindingHandlers.initializeValue = {
init: function(element, valueAccessor) {
if (element.getAttribute('value')) {
valueAccessor()(element.getAttribute('value'));
} else if (element.tagName === 'SELECT') {
valueAccessor()(element.options[element.selectedIndex].value);
}
},
update: function(element, valueAccessor) {
var value = valueAccessor();
element.setAttribute('value', ko.utils.unwrapObservable(value));
}
}
NOTE: The initializeValue binding should appear before the value binding in your select's data-bind attribute or it will not work.
<select data-bind='initializeValue: layout_id, value: layout_id, options: layouts, optionsText: "text", optionsValue: "id"'></select>