A little late here. I wasn't actually satisfied with RP's answer, because it breaks the declarative nature of Knockout. Specifically, if you use valueWithInit to define your property, you can't use it in an earlier binding. Here's a fork of his jsfiddle to demonstrate.
You use it the same way, yet it's still document-wide declarative under the hood:
<input data-bind="valueWithInit: firstName" value="Joe" />
Extending on the idea, you can also use this to separate the initialization and the binding:
<input data-bind="initValue: lastName, value: lastName" value="Smith" />
This is a little redundant, but becomes useful when you're using a plugin instead of the built-in bindings:
<input data-bind="initValue: lastName, myPlugin: lastName" value="Smith" />
Expanding a little more, I also needed a way to initialize checkboxes:
<input type="checkbox" data-bind="checkedWithInit: isEmployed" checked />
And here are the handlers:
ko.bindingHandlers.initValue = {
init: function(element, valueAccessor) {
var value = valueAccessor();
if (!ko.isWriteableObservable(value)) {
throw new Error('Knockout "initValue" binding expects an observable.');
}
value(element.value);
}
};
ko.bindingHandlers.initChecked = {
init: function(element, valueAccessor) {
var value = valueAccessor();
if (!ko.isWriteableObservable(value)) {
throw new Error('Knockout "initChecked" binding expects an observable.');
}
value(element.checked);
}
};
ko.bindingHandlers.valueWithInit = {
init: function(element, valueAccessor, allBindings, data, context) {
ko.applyBindingsToNode(element, { initValue: valueAccessor() }, context);
ko.applyBindingsToNode(element, { value: valueAccessor() }, context);
}
};
ko.bindingHandlers.checkedWithInit = {
init: function(element, valueAccessor, allBindings, data, context) {
ko.applyBindingsToNode(element, { initChecked: valueAccessor() }, context);
ko.applyBindingsToNode(element, { checked: valueAccessor() }, context);
}
};
Notice valueWithInit
simply uses initValue
under the hood.
See it in action on jsfiddle.