I'm brand new to Knockout.js and have been following a tutorial. However, my code is not working as expected, because in my custom binding createDecimal
, valueAccessor()
is returning the signature of the function instead of the actual value.
I'm using the latest version of Knockout.js as of today, v3.4.2.
<p>First Name <strong data-bind="text: firstName"></strong></p>
<p>Last Name <strong data-bind="text: lastName"></strong></p>
<p>Change First Name <input data-bind="value: firstName, valueUpdate: 'afterkeydown'" type="text" name="firstName"></p>
<p>Change Last Name <input data-bind="value: lastName, valueUpdate: 'afterkeydown'" , type="text" name="lastName"></p>
<p>Full Name: <strong data-bind="text: fullName"></strong></p>
<p>Add new hobby: <input data-bind="value: hobby, valueUpdate: 'afterkeydown'" type="text" name="hobby"><button data-bind="click: addHobby">Add</button></p>
<p>Hobby to possibly be added: <strong data-bind="text: hobby"></strong></p>
<ul data-bind="foreach: hobbies">
<div>
<li data-bind="text: $data"></li>
<button data-bind="click: $parent.removeHobby">Remove Hobby</button>
</div>
</ul>
<p>Total Number of Properties: <strong data-bind="makeDecimal: numberOfHobbies"></strong></p>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script type="text/javascript">
ko.bindingHandlers.makeDecimal = {
update: function(element, valueAccessor) {
var numberOfHobbies = valueAccessor();
console.log("Number of Hobbies", numberOfHobbies);
var formattedText = "$" + numberOfHobbies.toFixed();
element.innerText = formattedText;
}
};
function IndexViewModel() {
var self = this;
self.firstName = ko.observable("George");
self.lastName = ko.observable("Lopez");
self.hobby = ko.observable();
self.hobbies = ko.observableArray(["Acting", "Joking", "Speaking"]);
self.addHobby = function() {
self.hobbies.push(self.hobby());
};
self.removeHobby = function(hobby) {
self.hobbies.remove(hobby);
};
self.fullName = ko.computed(function() {
return self.firstName() + " " + self.lastName();
});
self.numberOfHobbies = ko.computed(function() {
return self.hobbies().length;
});
}
ko.applyBindings(new IndexViewModel());
</script>
It's not natural, but here you need to use ko.unwrap()
to get the value of the observable.
ko.bindingHandlers.makeDecimal = {
update: function(element, valueAccessor) {
var numberOfHobbies = ko.unwrap(valueAccessor());
console.log("Number of Hobbies", numberOfHobbies);
var formattedText = "$" + numberOfHobbies.toFixed();
element.innerText = formattedText;
}
};
It's because of the way Knockout manage observables, by replacing them by functions.