I have implemented the extender shown in the Knockout live 1 example - https://knockoutjs.com/documentation/extenders.html
ko.extenders.precision = function (target, precision) {
//create a writable computed observable to intercept writes to our observable
var result = ko
.pureComputed({
read: target, //always return the original observables value
write: function (newValue) {
var current = target(),
roundingMultiplier = Math.pow(10, precision),
newValueAsNum = isNaN(newValue) ? 0 : +newValue,
valueToWrite =
Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;
//only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
},
})
.extend({ notify: "always" });
//initialize with current value to make sure it is rounded appropriately
result(target());
//return the new computed observable
return result;
};
The view model is as follows:
model.gwaioDifficultySettings = {
minionMod: ko.observable(0).extend({
precision: 3,
rateLimit: { timeout: 500, method: "notifyWhenChangesStop" },
}),
};
And it's accessible through an HTML input field:
<div>
<input
type="number"
style="width: 50px; padding-bottom: 0px;"
data-bind="textInput: model.gwaioDifficultySettings.minionMod"
/>
<span style="margin-left: 6px;"></span>
<loc>Minion Modifier</loc>
<span
class="info_tip"
data-bind="tooltip: '!LOC:Mandatory Minions + Star Distance * Minion Modifier = number of additional enemy Commanders.'"
>?</span
>
</div>
However, I've had to add rateLimit: { timeout: 500, method: "notifyWhenChangesStop" }
, else I find that the field will remove the decimal point once the value is an integer, and then it will prevent any attempts to enter the decimal point again.
This doesn't appear to be the case in the live example, and I'm wondering where I've gone wrong, or if it's simply due to the environment I'm working in with Knockout 3 and Chromium 28.
I added some code from https://gist.github.com/gnab/7579584 to my extender:
if (_.isString(newValue)) {
newValue = newValue.replace(",", ".");
newValue = parseFloat(newValue);
if (!isNaN(newValue)) {
target(newValue);
}
}
This results in:
ko.extenders.precision = function (target, precision) {
//create a writable computed observable to intercept writes to our observable
var result = ko
.pureComputed({
read: target, //always return the original observables value
write: function (newValue) {
if (_.isString(newValue)) {
newValue = newValue.replace(",", ".");
newValue = parseFloat(newValue);
if (!isNaN(newValue)) {
target(newValue);
}
}
var current = target(),
roundingMultiplier = Math.pow(10, precision),
newValueAsNum = isNaN(newValue) ? 0 : +newValue,
valueToWrite =
Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;
//only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
},
})
.extend({ notify: "always" });
//initialize with current value to make sure it is rounded appropriately
result(target());
//return the new computed observable
return result;
};
In all my tests so far this seems to perform as required. It will leave a hanging decimal point visible if one is entered, but this doesn't appear to have any negative consequences.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.