Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knockout.js input box event change - passes old value

When adding a change event binding to an input box using knockout.js the old value is passed to the change function when the event is fired. I can work around this by using blur. Is this the intended behavior? Is the idea to use the change event to have the old value and then use a normal selector to get the value from the dom? It seems counter intuitive.

jsFiddle Example

JavaScript ---------- var data = {     saved_value:"1",     value_changed: function(data){         alert(data.saved_value());     } }; var viewModel = ko.mapping.fromJS(data); ko.applyBindings(viewModel);  HTML ---- Current Value:<span data-bind="text:saved_value"></span><br/> <input data-bind="event:{change:value_changed},value:saved_value"></input> 
like image 791
Ominus Avatar asked Mar 03 '12 03:03

Ominus


People also ask

What is $data in knockout?

In the root context, $data and $root are equivalent. Inside a nested binding context, this parameter will be set to the current data item (e.g., inside a with: person binding, $data will be set to person ). $ data is useful when you want to reference the viewmodel itself, rather than a property on the viewmodel.

How do I assign a value to knockout observable?

To create an observable, assign the ko. observable function to the variable. A default value can be specified in the constructor of the call. Knockout then converts your variable into a function and tracks when the value changes, in order to notify the UI elements associated with the variable.

What is two way binding in knockout JS?

KO is able to create a two-way binding if you use value to link a form element to an Observable property, so that the changes between them are exchanged among them. If you refer a simple property on ViewModel, KO will set the form element's initial state to property value.


2 Answers

Update: For newer versions of knockout, you can replace the value binding with textInput, which handles many edge cases not covered by valueUpdate.


No, this is not the right way to do things.

You're getting the old value because saved_value doesn't get updated until the textbox loses focus.

If you want to push the new value in as the user types, using the valueUpdate option of the input binding:

<input data-bind="event: { change: value_changed }, value: saved_value, valueUpdate: 'afterkeydown'" /> 

The valueUpdate option takes an event name (e.g. 'keyup'). When that event fires, your saved_value will be updated.


Now let me propose an alternate solution.

Still do the valueUpdate binding like I showed above, but instead of listening for the changed event, just subscribe to the observable:

<input data-bind="textInput: saved_value" /> 

Then in JS:

var viewModel = {     saved_value: ko.observable("1"), }; viewModel.saved_value.subscribe(function (newValue) {    alert(data.saved_value()); }); ko.applyBindings(viewModel); 
like image 148
Judah Gabriel Himango Avatar answered Sep 24 '22 13:09

Judah Gabriel Himango


If you put the 'event' option at the end you don't need the 'valueUpdate' option. Like this:

<input data-bind="value: saved_value, event: { change: value_changed }" />

Also note that when you make use of subscribe to an observable, it gets triggered every time your value changes. (either by user interaction or programmatically).

like image 37
Fragy Avatar answered Sep 23 '22 13:09

Fragy