AngularJS ng-change whenever input changes - javascript

I have an input of type email:
<input type="email" ng-model="user.email" name="email" required>
Now I need to execute some code whenever the input is changed. Adding an ng-change="emailInputChanged()" only executes my method, in case the entered string is a valid e-mail address, but I need the callback to be executed with every keystroke, even though the input does not validate. (same issue of course when watching the model à la $scope.$watch('user.email', emailInputChanged).
Any angular way to do so?

I suggest to use the onInput event: http://www.w3schools.com/jsref/event_oninput.asp
Create a custom directive and listen for the "input" event on your text field element.
Example of the directive implementation:
function OnInput() {
return {
restrict: 'A',
template: '',
scope: {
whenInputChanged: '&'
},
link: function($scope, $element, $attrs) {
$element.on('input', $scope.whenInputChanged);
}
};
}
angular.module('App')
.directive('onInput', OnInput);
To apply the event listener in the template:
<input type="email" on-input when-input-changed="change()" name="email" required/>
Enjoy!

since you have given the type as email it will call the ng-change only when its a valid so remove the type attribute

Use ng-keyup instead. This would be the same even with basic (native or jQuery) events, as form will react normally only on field blur.
To catch also paste events, use the ng-paste directive (see https://code.angularjs.org/1.4.6/docs/api/ng/directive/ngPaste)

Related

Google Chrome issue: Model for input type 'password' not updated but 'text' does when browser autofills saved values

I have a login Form that is validated using Angular validation as follows:
HTML for Input fields:
<input id="loginName" name="loginName" type="text" class="form-control" placeholder="Username" data-ng-model="loginName" data-ng-maxlength="246" required>
<input id="password" name="password" type="password" class="form-control" placeholder="Password" data-ng-model="password" data-ng-maxlength="246" required>
'Login' button is validated against loginName and password fields using angular validation.
In Google Chrome (other browsers behave as intended) when these fields are saved (with do you want to save username and password feature) when the page is refreshed, the model for input type 'text' -> $scope.loginName gets updated with the saved value on the other hand the model for input type 'password' -> $scope.password is always empty) and according to the validation logic form is declared invalid and the 'Login' button stays disabled even though both the input fields are populated with saved information (See first attached image).
The moment a keypress or mouse click even occurs(not necessarily on the input fields but anywhere on the web page), somehow the model for password is updated and form is validated as shown in the second image attached.
I tried using autofocus, custom autofocus directives, timeouts but it doesn't seem to work as intended.
any suggestions, probably moving the cursor to the end of the text field so that the form knows that the text has been entered in the password field by the browser?
Came across this: AngularJS browser autofill workaround by using a directive
NOTE: All he answers in above solution talk about input elements value, got by either .val() or .value methods but the tricky part is both return undefined in case of password input field.
But no luck!
Thanks.
You may use
$scope.$watch('modelValue',function(newVal,oldVal){
//your code action
});
which will keep on tracking the model value. Whenever the model has value, your code inside $scope.$watch will be triggered.
As suggested by Ziv Weissman (in the comments section above) and after wasting quite a few hours on this, I have abandoned the AngularJs style validation process for the Login button and the input type password as well.
Chrome pretends it does not have a value for the field as a security measure. There's no way to hack around that. from: here
I found a potential solution to this behaviour which involves re-capturing the password value after a delay.
Just add this directive,and call the directive from the input's
Directive code
Modeule.directive('autoComplete', function ($timeout) {
return function (scope, iElement, iAttrs) {
iElement.autocomplete({
source: scope[iAttrs.uiItems],
select: function () {
$timeout(function () {
iElement.trigger('input');
}, 0);
}
});
};
});
HTML code
<input type="text" ng-model="username" auto-complete />

Angularjs input field focus event?

i use angularjs and i have created a normal input field like this:
<input type="text" style="border: none" ng-model="model" >
i want do the following:
if someone clicks in the input field, i want call for example method A. Then he writes text in this field and if the person clicks somewhere in my page so that the input field is no longer focused it should call method B. is this possible with angularjs ? if yes, how can i do that ?
ng-focus is only active at the input event but not at the output..
i want lock something with this, method A sets only a value to true and method B sets the same value to false. but i must know when the input field is active and when not.
You are looking at ng-focus and ng-blur.
<input type="text" style="border: none" ng-model="model" ng-focus="A()" ng-blur="B()">
On a side note, use css classes instead of inline styles.. :)
Or just call the same method with argument and set the value acc:-
<input type="text" style="border: none" ng-model="model" ng-focus="A(true)" ng-blur="A(false)">
If you are using functionality that you may wish to apply to fields throughout your application, you could put the it into a directive.
Here is an example that adds and removes a css class based on the focus or blur of a field:
angular.module('myApp').directive('inputFocus', function () {
var FOCUS_CLASS = 'input-focused';
return {
restrict: 'A',
priority: 1,
require: 'ngModel',
link: function (scope, element, attrs, ctrl) {
element.bind('focus',function () {
element.parent().addClass(FOCUS_CLASS);
}).bind('blur', function () {
element.parent().removeClass(FOCUS_CLASS);
});
}
};
});
You can bind method B to angular's ng-blur directive to detect when an input loses focus
<input type='text' ng-focus='methodA()' ng-blur='methodB()' ng-model='model'>

AngularJs Ng-Keypress event working wrongly?

I am developing an application in Angularjs. I am using ng-keypress event in input type=text. While typing value in text I'm getting wrong values in the keypress function. For example, the first time if I type "1" I am getting undefined. Second time, typing any other value gives the first value
<input ng-model="NodeId_1" type="text" ng-keypress="getValue()"/>
var angularapp = angular.module('nameapp', []);
angularapp.controller('NameCtrl', function ($scope) {
$scope.getValue = function () {
alert($scope.NodeId_1);//Here first time undefined is coming and second what ever we enter first value will come
}
}
)
You'll want to use ng-keyup instead.
ng-keypress happens as the key is pressed, and BEFORE the value populates the input. This is why you're not getting any value on the first keypress, but on subsequent presses you will.
Use ng-keyup and your problem is solved, as it happens once the value has already populated the input.
<input ng-model="NodeId_1" type="text" ng-keyup="getValue()" />
ng-keypress is working as intended, but it is not the directive applicable to your requirements.
Working plunkr: http://plnkr.co/edit/OHWDZo68siDlcrXnLyzJ?p=preview
The keypress event is fired when a key is pressed down and that key
normally produces a character value (use input instead).
https://developer.mozilla.org/en-US/docs/Web/Events/keypress
So neither the input field value nor the scope value(apply/digest loop etc.) will reflect the expected input value.
Solution is depending on your requirements. Here are some:
1) Use another event on the inputfield: change, keyup, ...
2) Use the $event object in your listener method:
<input ng-model="NodeId_1" type="text" ng-keypress="getValue($event)"/>
$scope.getValue = function (event) {
console.log(event)
}
3) Create a watcher for your NodeId_1 value within your scope:
$scope.$watch('NodeId_1', function(newVal) {
...
});
The watcher function work for me, I attached my example
$scope.$watch('itemm.montoAmodificar', function (newValue) {
$scope.fnActualizarNuevoSaldoDependencia(parseFloat(newValue));
});
The html code is the following
<input ng-model="itemm.montoAmodificar" my-focus class="form-control" type="text" placeholder="Ingrese el monto" ng-keypress="fnActualizarNuevoSaldoDependencia($event);" />

Angular Form Validation

I am stuck with certain scenarios in a validation. I need to valiadte a field - "First Name". Validations logic i have been using is -
If the field is dirty then validate against regex
ng-show="aspnetForm.FirstName.$dirty && aspnetForm.FirstName.$error.nameValidate"
If the field is marked required (currently keeping the field required is entirely business dependent so i am reading the true/false value from a JSON) then user may try submitting the form as it is
ng-show="blankSubmit && aspnetForm.FirstName.$error.required"
where blankSubmit is just a scope variable i am setting true on submit button click.
Now 3rd scenario is the logic i am not getting that is if the user clicks on the firstname text box and then without dirtying it, just blurs out, then the validation message should be displayed if ng-required is set true.If i just place ng-show="aspnetForm.FirstName.$error.required" then on the page load itself the error message is displayed which i dont want as it gives user a bad UX.
I solely want error message to be displayed when the attribute ng-required is set true and user blurs out of the textbox.
One possible solution is to create a directive which marks a field as visited which you can then check in the ng-show:
.directive('visited', function() {
return{
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ngModel){
element.bind('blur', function(){
scope.$apply(function() {
ngModel.visited = true;
});
});
}
};
});
View:
ng-show='form.field.$error.required && (form.field.$dirty || form.field.visited)'
I would suggest you using ng-messages. Your HTML would look like this:
<div ng-messages="aspnetForm.FirstName.$error" role="alert">
<div ng-message="required">Please enter a value for this field.</div>
<div ng-message="nameValidate">This field must be a valid.</div>
...
</div>
In case you want to use required depending on some variables I would suggest you using this <input ... required={{shouldBeRequired}}/>. This should work, required field should be validated only when proper value is set to it.

How to create an AngularJS directive that binds to a variable?

I want to build a directive for showing datepicker textboxes, i.e regular textboxes which have JQuery UI's datepicker used on them, so when the user clicks them, a datepicker box opens to let them pick the date, etc.
I want to bind this directive somehow to a property on my scope. E.g if it were a normal textbox and I did ng-model='myDate' then $scope.myDate would be updated if the user typed in a new date. In the same way, I want to bind this field from the directive so when the user picks a date, it updates the scope property its bound to.
The problem is, I want to display the directive using something like this:
<datepicker name='something' value='2013-07-20' model='myProperty' />
And have the directive replace it with the <input type="text" /> etc. So I can't use ng-model.
How else can I bind the model property to the directive so that it updates whenever the user changes it?
See if this is what you want:
HTML
<div ng-app="app" ng-controller="Ctrl">
<foo model="property"></foo>
<input type="text" ng-model="property">
</div>
Javascript
angular.module('app', [])
.directive('foo', function() {
return {
restrict: 'E',
replace: true,
scope: { model: '=' },
template: '<input type="text" ng-model="model">'
};
})
.controller('Ctrl', function($scope) {
$scope.property = 'Foobar';
});
jsFiddle
In order to use ng-model instead of model, you'll need to wrap the input in a container tag. Here's another jsFiddle script that illustrates it.
Finally, there's a date picker control in Angular UI Bootstrap. Perhaps it already does what you need.

Categories