4

Using the latest knockout 3.3.0 and jquery 1.11.0, any changes made to an input element from JS will not update observables bound to that element via textInput or value.

Example mock code:

html

<input id="test" type="text" data-bind="textInput: testObs" />

js

$("#test").val("someVal");

Example fiddle: http://jsfiddle.net/whxj5Lf6/

Is there a workaround to this so that such changes will be caught?

Slight
  • 1,541
  • 3
  • 19
  • 38
  • you are setting value using jquery at the time of button click ! – PaulShovan Jul 02 '15 at 22:00
  • @gypsyCoder Yes, that is the point of the button. It changes the element's value and shows that the observable had not been updated. It will not update no matter how many times it is pressed. – Slight Jul 06 '15 at 16:13
  • dont use jquery, use a knockout click, bind to a function that then updates your model. as you put above, it wont listen to value or textInput. Because its dirty, just update your model manually I.E myObject.Name('somename') the bindings will then show in the actual text box – davethecoder Jul 07 '15 at 15:09
  • @davethecoder It seems you've completely circumvented the question I'm asking for no good reason. I understand that you're supposed to update your observables via... the observable. Some component I'm using changes the input textbox text using jquery and I have no control over that. Why would the "change" event not fire when JS changes the input text? – Slight Jul 08 '15 at 15:22

2 Answers2

5

Knockout listens for events to know that the value has changed. Specifically it will respond to the change event, which is easy to trigger with jQuery:

$("#test").val("test2").change();

http://jsfiddle.net/mbest/whxj5Lf6/2/

When interfacing with external components, it's often better to use a custom binding rather than the built-in value or textInput bindings. For example, here's a custom binding for use with the jQuery UI datapicker.

Community
  • 1
  • 1
Michael Best
  • 16,623
  • 1
  • 37
  • 70
  • Is there an event I can hook so that a manual call to `.change()` is not needed? The code that is changing the element's value is a third-party component that I'd rather not modify. – Slight Jul 06 '15 at 16:15
  • What's the component? – Michael Best Jul 06 '15 at 19:31
  • It's a date range picker component that is based on jquery. Not sure why you care though, I can modify the source, I just don't want to as the event based approached is a much better design choice for a variety of reasons. – Slight Jul 08 '15 at 15:25
  • And if you're thinking about hooking some event the component fires, don't bother because it doesn't as per my reviewing the source code. My solution will be to modify the component's source due to my particular circumstances, but I think hooking some event is the real answer here, if you can do it. – Slight Jul 08 '15 at 15:37
  • Probably you should use a custom binding (maybe one is already written) such as the example I've linked to. – Michael Best Jul 08 '15 at 19:02
  • That's good advice and I am using a custom binding already, that doesn't change the problem at hand though which is that the component is capable of changing the input textbox without sending an explicit JS event. – Slight Jul 08 '15 at 22:16
  • Obviously that's a problem with the component you're using. In the binding I link to, you can see that the datepicker code generates a `changeDate` event. – Michael Best Jul 08 '15 at 23:49
  • Yes, the component could do things better, however, it'd be even better if the browser would fire an event when an input is changed by anything, regardless if it was from JS or user input. I think my options are clear at this point though. Thanks for the info. – Slight Jul 09 '15 at 13:36
1

According to knockoutjs documentation, the value of an observable will update when the change event will occur.

Whenever the user edits the value in the associated form control, KO will update the property on your view model. KO will always attempt to update your view model when the value has been modified and a user transfers focus to another DOM node (i.e., on the change event), but you can also trigger updates based on other events by using the valueUpdate parameter

There is only one valueUpdate parameter exists that matches the criteria of your problem. The input parameter but it has some limitations according to documentation...

"input" - updates your view model when the value of an or element changes. Note that this event is only raised by reasonably modern browsers (e.g., IE 9+).

So, I think the best choice for you is to take the solution provided by Michael Best, trigger the change() event manually as following...

$("#test").val("test2").change();
Community
  • 1
  • 1
PaulShovan
  • 2,140
  • 1
  • 13
  • 22
  • It seems the answer here is this "input" event so long as you're ok with excluding older browsers (IE 8 and below). Manually updating the variable is an obvious solution that doesn't properly answer the question IMO; it doesn't actually make ko "catch" anything. I'll mark this as the answer then. – Slight Jul 08 '15 at 15:32
  • This answer isn't correct. The `input` event is only triggered by user actions, not by JavaScript code (unless triggered specifically). See http://help.dottoro.com/ljhxklln.php – Michael Best Jul 08 '15 at 23:58