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?
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.
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();
Related
I need to detect a change in a form's field, as I understand in Vue there are two ways to do that:
via v-on directive
via watch method
Which one would you recommend to use? Are they the same in terms of how much memory they use? Why would I prefer one to the other?
UPDATE
Just to explain what I need: I have a form and I need to send a Google Analytics ga event out each time somebody enters something in the field and then leaves it. v-on or watch?
You understand incorrectly. Use v-on to detect events like change or input on a form field. Use watch to detect changes in a reactive data item (data, computed, or prop).
If you use v-model on a field, you are implicitly using v-on to detect input (or change if using the .lazy modifier) and copy that value into a data item. If you are tempted to add another v-on to detect changes, you probably should watch the data that is already changing with the form field. The exception is if you specifically need to know that the change came from the form field and there might be other ways it could change.
We have an input of type number with a knockout binding like this:
<inputtype="number" data-bind="value: quantity" />
This works perfectly on Chrome and EDGE but not on Firefox. Whenever we change the value and press save, the value gets reset to the previous value.
Any idea why this is not working?
Please use 'textInput' binding instead of 'value' for 2-way bindings. From the documentation:
Browsers are highly inconsistent in the events that fire in response
to unusual text entry mechanisms such as cutting, dragging, or
accepting autocomplete suggestions. The value binding, even with extra
options such as valueUpdate: afterkeydown to get updates on particular
events, does not cover all text entry scenarios on all browsers.
The textInput binding is specifically designed to handle a wide range
of browser quirks, to provide consistent and immediate model updates
even in response to unusual text entry methods.
http://knockoutjs.com/documentation/textinput-binding.html
In case it doesn't help, please post your view model and recheck that there are no other event handlers bound to the same DOM element.
I have a situation here, the valueChanged gets called even if I change the bindable property value internally within custom element. How do I send the updated value back to viewModel from custom element without triggering valueChanged for that bindable value.
is there a way to supress this? or I have to use internal tracking if this is called from internal code or coming from view?
There is no way to prevent a bindable property's change handler method from being called based on whether the custom element's own code is assigning the property or whether it's being assigned by external code or in response to user input. You will have to roll your own internal tracking mechanism.
As Jeremy said, there's no way to prevent a bindable property's change handler from being called. However, you could attach or trigger your code only with the form input using the change.delegate or keyup.delegate properties. That would allow you to isolate your event code from the changes resulting from binding properties.
Here's a GistRun to demonstrate this:
https://gist.run/?id=11cd1e90dd912f07a60afaedb9c2613b
I have a very simple use case in my application. when user double click on a record it will show an input box and after submitting new text and hit enter. that will update the record.
all I want to do is grab input elements value and fire service.
<input type="text" ng-model="updatedListTitle" ng-enter="updateList(list.id, updatedListTitle)">
as you can see I am using ngmodel to grab data in my controller. the problem is with every keystroke it is firing all my watchers unnecessarily (even though i know angular is fast and you can fire like 1000 watcher and all ). but just grabbing the element using jquery would be more efficient.
is there any better approach to handle these situation where i really don't care about 2 way binding
Well..., in my opinion the way you have done it is perfectly idiomatic angularjs and I wouldn't start to micro-optimize it.
(Remember "Premature optimization is the root of all evil" as well as Michael A. Jacksons rules about optimization and other quotes - http://en.wikipedia.org/wiki/Program_optimization )
No, I don't think there is any sensible way to do it without jQuery (or at least jqLite or manual dom access).
If you do that, you should encapsulate it in a directive (which arguably is the only place explicit DOM access/manipulation should be).
Can you use ng-blur here instead of ng-enter and then check to see if the model is dirty and then do the service call?
AngularJS sets the CSS classes ng-pristine and ng-dirty on any input field you've used ng-model on, and your controller has the properties $pristine and $dirty which you can check to see if the form is dirty or not.
That might be a bit more optimized. I would still do this in a directive though.
I am having a form, which comprises of several textboxes and one button.
I am using the Kendo UI MVVM format. How shall I get the value of each textbox and store it in an object on click of the button?
Will I have to use normal jQuery in order to get the values or is there some other way of getting the values from each of them?
Thanks
Hardik
Please take a look at these documentation pages:
http://demos.kendoui.com/web/mvvm/index.html
http://docs.kendoui.com/getting-started/framework/mvvm/observableobject
http://docs.kendoui.com/tutorials/mvvm-in-kendo-ui
These pages contain answers to most of the questions you'll have concerning Kendo UI MVVM. It would be silly and presumptuous of me to think that I could explain it better than the qualified and hard working individuals at Telerik that have so painstakingly compiled these documentation pages.
The gist of it is that you need to create an instance of the kendo.data.ObservableObject that has properties for the values you are working with. This is your view-model. Then in your markup for your text boxes, include values for the data-bind attribute that reference the properties in your observable object. Create a function in your view-model to handle the button's click event. Put a data-bind attribute in your button that binds the click event to your function. Finally, call kendo.bind(<element>, <observable object>), and that will connect the wires from your markup to your view-model object.
In your click event-handler, you can take the values of the view-model, and insert them into the object you need. You should not need to use "normal jQuery" for anything besides referencing the element to call bind on.
Quickly you can retrieve the value this way using JQuery:
$('#yourTextBoxID').data('kendoMaskedTextBox').value();
you can use this code:
$('#yourTextBoxID').val();