Suppose you have an input field in an Angular JS app
<input id="title" type="text" name="title" placeholder="enter a title" ng-model="item.title" />
I would like to display some feedback to the user about the validity of the input data AFTER the user has completed interacting with the input but I cannot think of a directive to watch the "click off" event. That is, when a user types into the form, then either tabs next or clicks anywhere else.
How do I capture the "click off and element" event.
Please note, this is in contrast to an "off-click" event, where the event refers to when a user clicks anywhere BUT a given element.
You need to use ng-blur directive.
ng-blur:
Specify custom behavior on blur event.
A blur event fires when an element has lost focus.
Note: the print you see in the ng-blur is nothing but console.log using this for convenience, refer my fiddle!
JSFiddle Demo
JS:
<div ng-controller='MyController' ng-app="myApp">
<input id="title" type="text" name="title" placeholder="enter a title" ng-model="item.title" ng-blur="print('lost focus')" />
</div>
References:
ng-blur
As mentioned in Naren's answer, ngBlur is the directive you are looking for.
However, since you're trying to implement validation, you should know that angular has built-in validation functionality that will handle the events for you and using them is a better practice than reinventing the validation 'wheel'.
Use validation directives like ngRequired, ngMinlength, ngMaxlength and ngPattern for simple validation needs.
https://docs.angularjs.org/guide/forms
Use Angular UI's uiValidate directive for custom validation including validation through asynchronous http requests.
https://github.com/angular-ui/ui-validate
Related
I have an Angular 4 form, but with the data tracked in an injected service (for reasons outside the scope of this question).
Each input looks something like...
<input name="..." [ngModel]='getVal(...)' (ngModelChange)='setVal(...)'>
...because there's extra functionality in those getters/setters.
That's working great, but I would also like to use the built-in validation. If I give my form a template reference variable...
<form id="..." #myForm="ngForm">
and look at the value of myForm, it's not tracking any of those inputs. I get that, I mean, I'm specifically telling it to track them elsewhere.
But how can I take advantage of the built in HTML5 validation? i.e. required and pattern
You can use validation like this in your html. This is template based validation as per your requirement.
Submit button will not be active till all the fields are validated.
<form (ngSubmit)="submitFunc()">
<input name="name" [ngModel]='getVal(...)' (ngModelChange)='setVal(...)'
required pattern=""> //required pattern here
<button [disabled]="!myForm.form.valid" type="submit">Submit Form </button>
</form>
You have to add required in your input field and specify pattern with a regular exression.
vuejs-datepicker setting html required attribute on input fields doesn't work as expected and submits the form without have a input value.
<form>
<datepicker placeholder="Select Date" required></datepicker>
<button>Submit</button>
</form>
You can use the above code and test here:
https://codesandbox.io/s/p92k8l717
Here is the link to repo and doc: https://github.com/charliekassel/vuejs-datepicker
You can use vee-validate library to validate this like:
<date-picker :input-class="{'input': true, 'is-danger': errors.has('date') }"
v-model="date"
:disabled="state.disabled"
placeholder="Select date"
input-class="form-control"
></date-picker>
<span v-show="errors.has('date')" class="help is-danger-red">{{ errors.first('date') }}</span>
<input type="hidden" name="date" v-validate="'required'" v-model="date">
You can use this trick to solve this issue, It's works for me.
You can use input-attr to set the required attribute like :input-attr="{required: 'true'}"
I was facing the similar issue, not with this plugin but some other plugin and one get around that worked for me was using vee-validate
This is the best validation plugin available for vue-js.
Hope this helps!
A non-Vue datepicker library flatpickr also has this problem. I managed to resolve it by allowing user input (typeable prop of this library) which removes the readonly attribute which actually prevents the form submission on empty required field and also displays the native browser popup. The side effect is a date can now be directly typed into the input field which then forces you to parse the user input. To make up for that you have to suppress all user input in the field.
See the similar flatpickr question where I posted the complete solution. I used the onReady event of flatpickr which seems to have no equivalent in vuejs-datepicker settings unfortunately.
Flatpickr can be used in Vue thanks to vue-flatpickr-component library if you are OK with migrating.
I have the following code :
<input type="text" id="productCode" name="productCode" style="min-height: 42px;" onChange="ajaxrequest_provideProductListOnHit('protected/snippet/snippet_provideProductListOnHit.php', 'ajaxOnProductHit'); return false;" required="required" autofocus />
The problem is that :
The autofocus is not working, I'm using it in this input box only.
Actually the purpose of this input box is to get the field autofocussed so that a barcode scanner could input the productCode.
Now as you can see, my onChange event handler is not going to work here since the barcode scanner apart from the product code, inputs too.
So I need a solution here which autofocuses and once the barcode scanner inputs value in the field, calls for the mentioned ajax function.
html:
<input type="text" id="productCode" name="productCode" style="min-height: 42px;" required="required" autofocus />
js:
var pc = document.getElementById('productCode');
pc.onblur = function () {
ajaxrequest_provideProductListOnHit(
'protected/snippet/snippet_provideProductListOnHit.php',
'ajaxOnProductHit'
);
}
pc.focus();
i use onblur, because onchange would trigger after EVERY change you make (e.g. typing into the text-field will trigger after every key).
you could also provide some custom-logic, e.g. recognize a certain length
Yes you where right, the problem was that I was using autofocus on a different preceding form field which made this particular field of this particular form non-autofocus. So I learned that in a page with multiple forms loaded in to the DOM, only the first one with auto-focus will work. Fool of me to think otherwise.
I have an angular form which was using angular's built-in validation successfully. Take the following markup for example:
<form name="numberForm" novalidate>
<input type="text" required />
<button type="submit">Submit</button>
</form>
When the browser loads, the input field renders like this (unnecessary attributes removed):
<input class="ng-pristine ng-invalid ng-invalid-required" />
If I were to enter a value in the input field, the markup turns into:
<input class="ng-dirty ng-valid ng-valid-required" />
All of this was working great. Then I implemented two jQuery plugins to implement some masking/input formatting for the form: autoNumeric and jQuery.maskedinput. Now, nothing I do will change the original ng-pristine ng-invalid... classes on the input. It also doesn't seem to allow the binding of models to be successful either.
Any ideas?
I tried creating a http://jsfiddle.net/ma44H/3/, but can't seem to figure out how to get it to work.
JQuery and Angular do not cooperate well
Chocolate and Peanut Butter taste great together, but AngularJS and JQuery are a painful mix. We've all tried (with varying success) to accomplish this.
The problem is that JQuery DOM manipulation works outside of AngularJS Digest Cycle. The lesson is usually that using pure Angular is better.
Alternative #1: Angular UI
Try Angular-UI. Set of tools every Angular Developer could use.
Whatever Mask you want to implement can be done with their ui-mask directive:
Want a Date Mask?
<input type="text" ng-model="date" ui-mask="99/99/9999" />
Currency Mask?
<input type="text" ng-model="currency" ui-mask="$99999999.99" />
Phone Mask?
<input type="text" ng-model="phone" ui-mask="1 (999) 999-9999" />
:
See Fiddle
:
Alternative #2: Filters
Angular has built-in filters:
Currency:
$filter('currency')(amount, symbol)
Date:
$filter('date')(date, format)
Insist on using JQuery? Try the jQuery Passthrough directive from the angular-ui toolset. I haven't made use of this directive but it's an intriguing option:
To call something like $.fn.tooltip() simply do ui-jq="tooltip". Note
that the name of the function must be identical. This also works for
normal jQuery commands such as $.fn.slideUp().
To pass parameters use the ui-options attribute. The value will be
evaluated in the $scope context and passed to the function. If
defaults are set, the passed options will extend them. If a string is
passed, the default options will be ignored.
Use the directive name jq for namespacing inside uiJqConfig. Then
sub-namespace options for each function by the name of that function
(exactly as it is passed to ui-jq) so that you don't have to pass
options every time you call the directive.
I have two fields in my form, I need handle event when browser changes value of them, my fields are username and password; I've used this $('input').on('input change',function(e){//...}), but when I select a user name in list that popped up by my browser, value of password changes but 'input' event of password not working in that case.
How can I handle that ?
Code:
HTML:
<form action="/">
<input name="username" type="text" />
<br />
<input name="password" type="password" />
<br />
<input type="submit"/>
</form>
Js:
$('input[type="password"]').on('change keyup',function(event){
console.log(event.type);
});
It's working when I'm typing in password field, but not working when browser auto complete is changing password value.
This is browser behavior, not about scripting. I think there is no easy way to go around this.
A workaround is to set up a timer to periodically check for changes in the field.
Another workaround is to set up the onfocus to capture the before value and onblur event to capture the after value and compare if the value changes.
If it's crucial to you to handle the event when the field value changes. I think you should disable browser auto complete by specifying autocomplete="off" on the field and optionally implement auto complete yourself.
For more information, see this link.
It should be $('input').on('change', function(e){//...}) as documentation says
.on( events [, selector ] [, data ], handler(eventObject) )
you can try with this also:
$('input[type=text], input[type=password]').on('change', function(e){//...})