Reputation: 872
I have a strange behavior in my app using AngularJS 1.5.8:
plunker (https://plnkr.co/edit/zaHVJeK8hdxk2gaOL9Pf?p=preview) and video(http://recordit.co/eszvfdfC9S)
ng-required
doesn't call ng-change
functioninput
AND removing them (input
is empty) ng-required
DOES call ng-change
functionexpected behavior?
input
AND removing them (input
is empty) ng-required
SHOULD NOT call ng-change
function. As it was at the beginning, and as it is when input has some valuePlease let me know if it's a bug or not. If not then why changing ng-required
calls ng-change
NOT always or even at all?
ANSWER IS FOUND-------------------------------------------------------------------------------------------------------
NgModelController has two properties: $viewValue (value entered by user) and $modelValue (value bound to your model). When the value entered by the user fails validation, NgModelController sets the model to undefined.
In AngularJS 1.3, they added the ng-model-options directive. It lets you configure how/when the model gets updated. You can use the allowInvalid option to prevent your model from being set to undefined:
ng-model-options="{allowInvalid: true}"
Upvotes: 9
Views: 2024
Reputation: 760
I think this is the reason. put an alert inside ng-change like this.
this.onChange = function() {
alert(this.val);
this.output+='Changed\n';
}
When you empty the box after completing it the value change between two values:
undefined when is required
'' when is not required
So By changing the radio box you call the ng-change, At the beginning you have
However when you have not started to type in the text box , radio box does not change the input value , because ng-change is for input. In the beginning we have undefined --> undefined
so nothing changed. then when you empty the input you have '' ---> undefined
.
Actually if you put this in your controller you get call ng-change at the beginning too.
this.val ='';
So if you replace your controller with this , you see ng-change is called even at the beginning.
angular.
module('myApp', []).
component('greetUser', {
templateUrl: 'tmpl.html',
controller: function GreetUserController() {
this.output='';
this.isRequired = false;
this.val ='';
this.onChange = function() {
this.output+='Changed\n';
}
}
});
Upvotes: 0
Reputation: 9804
This is happening because the ng-required is changing the attached modal value to undefined from blank when the required is set to false, due to this ng-change is fired since the modal changes.
Check in the plunker i have console.log the value of input and you can see the change of modal clearly.
angular.
module('myApp', []).
component('greetUser', {
templateUrl: 'tmpl.html',
controller: function GreetUserController() {
this.output='';
this.isRequired = false;
console.log(this.val);
this.onChange = function() {
console.log(this.val);
this.output+='Changed\n';
}
}
});
plunker : https://plnkr.co/edit/6IeIjIDahcmBIU4KSASJ?p=preview
Now the question arises that why not the on load/ first time the change event is not firing up that is because we are using this object rather then $scope.
Here 'this' vs $scope in AngularJS controllers
is a very good example which explains why until we manually enter the value in the input at least once the change event is not firing up.
in short this is happening because ng-change/ng-model works with scope variables. Once you manually enter value in the input element, the model binding happens with the scope, and the ng-change event start firing up.
Upvotes: 2
Reputation: 186
You should add
ng-model-options="{allowInvalid: true}"
So the final result will be
<input type="text"
ng-change="$ctrl.onChange()"
ng-required="$ctrl.isRequired"
ng-model-options="{allowInvalid: true}"
ng-model="$ctrl.val"
/>
Upvotes: 8
Reputation: 2174
I think you misunderstanding.
ng-required
and ng-change
is different things. doing different purpose, and not calling each other.
ng-change
is calling your function no matter what it's empty or not. It's call your method by it self, regarding to changes happening in the input.
ng-required
is just checking value if it's empty or not, If it is empty, mark it as invalid.
In order to get what you want, you have to check the validity inside the onChange function.
this.onChange = function() {
if( !$scope.$ctrl.form.$valid ) return;
this.output+='Changed\n';
}
Upvotes: 0