knockout.js - Wrapping Knockout's hasFocus to change an elements text when selected -
i have knockout binding handler called valuenumber
parses , displays numbers little globalize:
ko.bindinghandlers.valuenumber = { init: function (element, valueaccessor, allbindingsaccessor, viewmodel, bindingcontext) { // called when binding first applied element // set initial state, event handlers, etc. here var observable = valueaccessor(), properties = allbindingsaccessor(); var interceptor = ko.computed({ read: function () { var format = properties.numberformat || "n2", formattednumber = globalize.format(ko.utils.unwrapobservable(observable), format); return formattednumber; }, write: function (newvalue) { var currentvalue = ko.utils.unwrapobservable(observable), numbervalue = globalize.parsefloat(newvalue); if (!isnan(numbervalue)) { if (numbervalue !== currentvalue) { // value has changed update observable observable(numbervalue); } } else if (newvalue.length === 0) { if (properties.isnullable) { // if newvalue blank string , isnullable property has been set nullify observable observable(null); } else { // if newvalue blank string , isnullable property has not been set set observable 0 observable(0); } } } }); if (element.tagname.tolowercase() === 'input') { ko.applybindingstonode(element, { value: interceptor }); } else { ko.applybindingstonode(element, { text: interceptor }); } } };
to use pretty straightforward:
<input data-bind="valuenumber: cost, numberformat: 'n1', isnullable: true" type="text" value="" />
when input textbox loses focus value displayed based on numberformat property. if user had entered "1.123" in textbox above when tabbed out "1.1" left displayed in input value stored in observable 1.123.
this gets tricky.
when input element gains focus / becomes active element want display full value (the 1.123) users in input element. i've got idea depending on hasfocus achieve i'm not "correct" approach like.
i'm ideally hoping wrap within 1 binding handler rather introducing need markup.
update
based on robert westerlund's answer i've come jsfiddle demonstrates solution nicely. robert's solution restyled based on conventions used in built-in hasfocus
binding.
oh , completeness solution using globalize 0.1.1. having had quick @ github repo looks api globalize going change @ point in future.
it's hard "correct" approach be, i'll give sample of 1 approach @ least. first, add observable keep track of focus state.
var elementhasfocus = ko.observable(element === document.activeelement);
next, need make sure change value when onblur
or onfocus
events occur.
element.onblur = function(){ elementhasfocus(false); }; element.onfocus = function(){ elementhasfocus(true); };
the above 3 lines added in init
method, right before create interceptor
computed observable.
finally, update read-method of interceptor
make sure determines value based on focus state.
read: function () { if (elementhasfocus()) { return ko.unwrap(observable); // if use newer versions of knockout, have convenient ko.unwrap path ko.utils.unwrapobservable method. } else { var format = properties.numberformat || "n2", formattednumber = globalize.format(ko.utils.unwrapobservable(observable), format); return formattednumber; } }
Comments
Post a Comment