ng-blur the model's updated value is not avaiable in event - angularjs

I am using the ng-model-options to prevent my text input's model from being updated until the focus is lost. That part all works. However, I need to handle the event after the text input loses focus and the model is updated. In that event I need access to the NEW model's updated value, not the old one.
I am trying to use the ng-blur event, however, inside my handler the value is the old value, not the new value entered. Am I doing something wrong or is there a better way to get the newly committed model value after the text input loses focus?
<input type="text"
ng-model-options="{ updateOn: 'blur', debounce:0 }"
ng-model="vm.myModel.amount"
ng-blur="vm.handleBlurEvent(vm.myModel.amount)" />
vm.handleBlurEvent = function(item)
{
//alert(item.amount); //Old amount - not new amount entered
}

This is reworked from previous response by user1750537, delay the model update until control blur and then process the change once, no de-bounce required and the model value will be set before your change logic as expected.
<input type="text"
ng-model-options="{ updateOn: 'blur' }"
ng-model="vm.myModel.amount"
ng-change="vm.handleChangeEvent(vm.myModel.amount)" />
vm.handleChangeEvent = function(item)
{
alert(item.amount); //new shows the NEW amount :-)
}

I don't have better luck with debounce yet
but to make your things working here is the code
<form name="amountForm" >
<input type="text" name="amount"
ng-model-options="{ updateOn: 'blur', debounce:0 }"
ng-model="vm.myModel.amount"
ng-blur="vm.handleBlurEvent()" />
</form>
vm.handleBlurEvent = function()
{
alert($scope.amountForm.amount.$viewValue);
}
enjoy...

Thanks for those suggestions. I actually managed to get this to work by adding 1 option to the updateOn property of ng-model-options. By adding in 'default' everything worked!
ng-model-options = "{updateOn: 'default blur}" was the trick.
<input type="text"
ng-model-options="{ updateOn: 'default blur' }"
ng-model="vm.myModel.amount"
ng-blur="vm.handleBlurEvent(vm.myModel.amount)" />
vm.handleBlurEvent = function(item)
{
//alert(item.amount); //new shows the NEW amount :-)
}

Old question but I've found another way to read this value, I couldn't remove debounce with delay and what worked for me was using timeout:
$timeout(function(){
var amount = this.formName.amount.value;
});
I think this = ngModelController in above code.

How about using a watch?
You can do your logic once the model is updated like this:
$scope.$watch('vm.myModel.amount', function (newVal, oldVal) {
if (newVal != oldVal) {
//do your logic here.
}
}, true);

Related

Input text change checkbox model only once [AngularJS]

I have this
<input type="text" ng-click"function1()">
And this:
<input type="checkbox" ng-change="function2()" ng-model="stateCheck">
The functions do this:
$scope.function1 = function(){
$scope.stateCheck = false;
}
$scope.function2 = function(){
$scope.stateCheck = !$scope.stateCheck;
}
But the function1 just works the first time. Does anyone know why? Thanks.
ng-change="function2()"
ng-model="stateCheck"
These two events are conflicting with each other, Basically ng-model makes the $state.stateCheck=true and then functin2() $state.stateCheck=!$state.stateCheck makes it false. Due to this checkbox will always remain unchecked. function1() works fine

AngularJs ng-change event fire manually

<input type="checkbox" value="" ng-model="filterPrivateDocCheckBox" ng-click="dl.filterPrivateDocument(filterPrivateDocCheckBox, $event)">
<input st-search="target" class="input-sm form-control" ng-model="dl.documentTarget" ng-change="dl.change()" />
function filterPrivateDocument(val)
{
if(val)
this.documentTarget = 'Private';
}
When I clicked on checkBox I set the value into text box, but I saw ng-change event doesn't get fired. why?
And also When I type some value in text box I observe that ng-change event gets fired.
Any fix for this problem?
According to the docs:
The ngChange expression is only evaluated when a change in the input value causes a new value to be committed to the model.
It will not be evaluated:
if the value returned from the $parsers transformation pipeline has
not changed
if the input has continued to be invalid since the model
will stay null
if the model is changed programmatically and not by a
change to the input value
So it will not be triggered when it is changed by JavaScript (/angular).
What you can do, is trigger the change function yourself:
function filterPrivateDocument(val) {
if(val) {
this.documentTarget = 'Private';
this.change();
}
}
See this jsfiddle

ng-model - getting name and value of input box

I have an update function and a number of input boxes. Each input has an ng-blur attached to it so that the update function is called whenever the cursor leaves the box.
$scope.update = function(data) {
console.log(data); //outputs value in the textbox
//how can I output/access the key?
}
The input for name look like this:
<input type="text" ng-model="user.name" ng-blur="update(user.name)"/>
As I need to be able to post a JSON object in the form {"name" : "bob smith"} what's a good way of generating the "key" of the object bearing in mind that it will differ depending on the input box that's being used at the time?
EDIT ↓
I have made this jsfiddle to illustrate a way to do it more cleanly & that would scale more easily: http://jsfiddle.net/kuzyn/k5bh0fq4/5/
EDIT ↑
Why not simply pass a second string argument? It's not a fancy way to do it but it would work:
<input type="text" ng-model="user.name" ng-blur="update(user.name, 'name')"/>
And
$scope.update = function(data, key) {
console.log(key, data);
}
It might be a little more work but it is much more scalable. You could make use of the ng-form and naming your form inputs. By naming your form and inputs, you are creating a form reference on your scope via $scope[form-name]. Each named input within that form then sets an input reference via $scope[form-name][input-name].
I'm coding this in coffeescript (to preserve my sanity, sorry)
form
<form name="myForm">
<input name="name" ng-model="user.name" ng-blur="update(user)"/>
<input name="email" ng-model="user.email" ng-blur="update(user)"/>
<input name="other" ng-model="user.other" ng-blur="update(user)"/>
</form>
update & save func
# key is what changed in case you need to do something special on the put call to server
$scope.save = (data, key)->
# pseudo-code
$scope.update = (data)->
for name, input of $scope.myForm
if input?.$dirty
$scope.save data, name
break
docs - https://docs.angularjs.org/guide/forms
codepen - http://codepen.io/jusopi/pen/LGpVGM?editors=101

AngularJS - Pause binding of input field while focused

I have a data object that looks like this:
$scope.data = { value1: 'anyValue', value2: 'anyValue'};
This data object will be updated via polling every second.
In the view I'm showing the data in input fields like:
<input type="number" ng-model="data.value1"/>
<input type="number" ng-model="data.value2"/>
The user should be able to focus one of the input fields and enter a value. Now this is not possible, because every change that is made in the field will be overwritten, when the data object gets updated.
I don't want to pause the whole polling process, because the other input field should still show its updated value.
What is the best way to pause only the binding of the focused input field, while it is focused?
I suggest you do the following:
<input type="number" ng-model="data.value1" ng-focus="onFocus('value1')" ng-blur="onBlur('value1')"/>
<input type="number" ng-model="data.value2" ng-focus="onFocus('value2')" ng-blur="onBlur('value2')"/>
In your controller, something like:
$scope.onFocus = function(key) {
$scope.preventChange = key;
};
$scope.onBlur = function(key) {
$scope.preventChange = null;
};
And then whenever you do your polling and updating, check if the data key you are trying to update is the one in $scope.preventChange, and if so - don't change it.

How can I make angularjs ngChange handler be called only when user finishes typing

I have an input field, where I want to apply the variant of ngChange.
The input field is sort of binding with an ajax call, when user changes the input, the server side will process the data, however, I don't wanna make the call too often.
Say the user wanna input a really string, I want the call be made only after user finishes the word he is about to type.
Nevertheless, I don't wanna use event such as blur. What would be a better way to implement this, rather than setTimeout?
Use ng-model-options in Angular > 1.3
<input type="text"
ng-model="vm.searchTerm"
ng-change="vm.search(vm.searchTerm)"
ng-model-options="{debounce: 750}" />
Without ng-model-options -- In markup:
<input ng-change="inputChanged()">
In your backing controller/scope
var inputChangedPromise;
$scope.inputChanged = function(){
if(inputChangedPromise){
$timeout.cancel(inputChangedPromise);
}
inputChangedPromise = $timeout(taskToDo,1000);
}
Then your taskToDo will only run after 1000ms of no changes.
As of Angular 1.3, you could use Angular ng-model-options directive
<input ng-change="inputChanged()" ng-model-options="{debounce:1000}">
Source: https://stackoverflow.com/a/26356084/1397994
Write your own directive- this will only run the commands on myText based on the conditions you set
<input my-change-directive type="text ng-model="myText" />
.directive('myChangeDirective',function() {
return {
require : 'ngModel',
link : function($scope,$element,$attrs) {
var stringTest = function(_string) {
//test string here, return true
//if you want to process it
}
$element.bind('change',function(e) {
if(stringTest($attrs.ngModel) === true) {
//make ajax call here
//run $scope.$apply() in ajax callback if scope is changed
}
});
}
}
})

Resources