I currently use markup like this for all my ng-messages
<div ng-messages="myForm.fieldName.$error && (myForm.firldName.$dirty || myForm.$submitted)">
<div ng-message="required">This field is required</div>
<div ng-message="minlength">Your field is too short</div>
</div>
It's a bit messy though and I'd like to somehow override or extend ng-messages so that it automatically checks to see whether the field is dirty or the form that the field is nested inside (by walking up the DOM maybe?) is $submitted.
I'd like this to be the default behaviour on all ng-messages in my site and can't forsee a situation when I'd need to show error messages when the input hadn't been used and the form hadn't been submitted so I think it's safe to override that behaviour, I just don't know how to do it.
I know I can replace the ng-messages entirely but then I'd have to recreate all of the default behaviours of that directive and these might change in future angular versions so I'd rather just extend it if possible. I don't know whether Angular provides any hooks for this (I've vaguely heard of decorator methods?) or whether to make a sibling directive, something like "ng-custom-messages" which just hides the element if the conditions aren't met?
So, I have a couple of ideas but I need a bit of a nudge to show how to implement them, just a bit of skeleton code if anybody is feeling charitable?
The answer to this was unfortunately to write a new form directive which automaticalley set all fields to dirty when submission happens.
Here is a short snippet of code...
angular.forEach( formCtrl , function ( formElement , fieldName ) {
if ( fieldName[0] === '$' ){
return;
}
formElement.$setDirty();
}, this);
formCtrl.$setDirty();
scope.$apply();
I recommend instead using an ngIf on the element that uses the ngMessages. Note that ngMessages accepts the $error property of NgModelController (or FormController).
<div ng-if="myForm.fieldName.$invalid && (myForm.fieldName.$dirty || myForm.$submitted)"
ng-messages="myForm.fieldName.$error">
<div ng-message="required">This field is required</div>
<div ng-message="minlength">Your field is too short</div>
</div>
As an aside, you may find it more appropriate to use $touched instead of $dirty in order to postpone error feedback until the element has lost focus (or the form has been submitted).
Related
I have a interesting problem to solve, but I don't know how,
I have a dynamically inputs in my view, and the inputs in Angular are validated in realtime, but I don't want that, the angular inputs in input class "ng-invalid" and I want to add "ng-invalid" just when submit my form:
<div ng-if="conditionItem.field.id"
ng-class="{'error': FieldConditionsCtrl.feedback.type === 'error'}"
dynamic
input-router << Here is my how generates the inputs
source="conditionItem.field"
ng-model="conditionItem.situation[$index]">
</div>
When I modify the generated input, AngularJS inputs in my input class the following classes "ng-invalid ng-empty":
I want to add this classes just when submit to make the border red.
Any help for this issue?
Used the $submitted property of the ngFormController to qualify the setting of the error class.
ng-class="{error: form1.$submitted && form1.field1.$invalid}"
For more information, see
AngularJS Developer Guide - forms
Is there a simple way to make inputs and textareas with the ng-required attribute set to true invalid if it contains only spaces or blank characters ?
I'm looking for a generic way that would be applied to all my fields.
Note : I'm using angular 1.5.5
There is a way that you can set "ng-required=checkVar" and all input field you want to be validate in the same way can be put same class (class tag), e.x: class="check". Then you can bind an event handle function to all these fields as:
$('.check').on('click', function(e){
do your work (validating)
if (validated)
$scope.checkVar = true;
else
$scope.checkVar = false;
}
This is my idea.
Ok, so in the end I didn't manage to find a generic way.
I had to change every template, but it can be done quickly using the replace option of any IDE.
I replaced every <textarea occurences with <textarea ng-pattern="/^(?=.*\S).+$/"
So, ng-pattern was my solution choice, there's probably a better way though.
I have a multi-part form, and I was hoping to have an external next/prev navigation for it. However, I need to be able to validate each part of the form when I navigate to next.
I have the following sample form definition:
<form layout="column" name="nProfileForm1">
<md-input-container>
<label>City</label>
<input ng-model="profile.city" required="" name="nCity">
<div ng-messages="nProfileForm1.nCity.$error" ng-if="nProfileForm1.nCity.$touched&&!nProfileForm1.nCity.$valid">
<div ng-message="required">City is required.</div>
</div>
</md-input-container>
</form>
If the field is interacted with,then validation is working find and error text is correctly shown. However, I cant figure out a way to trigger the validation of all the form fields if external event takes place. It seems somewhat wrong to add own submit button to every form part. What I am looking for is something similar to what schema-form does:
$scope.$broadcast('schemaFormValidate')
Any ideas would be appreciated.
Essentially, int he following example I want the field to light up with red once I press next:
http://codepen.io/Vladimir_M/pen/OWEjOd
UPDATE: updated codePen to include one solution that I've found.
After some attempts I've found one way to achieve the effect I was after with minimal code. Getting the form's scope and setting the form's $submitted property to true does the trick. It evaluates the entire form.
$scope.doSubmit = function(){
var formScope = angular.element(nProfileForm1).scope();
formScope.nProfileForm1.$submitted = true;
}
Feel free to suggest better ways.
I need to code the following requirement. If it occurs that any form field changes, I need to hide a div with some content. My solution is using $watch with objectEquality == true for watching a complex object that bind to the form fields. But this complex object has around 100 fields to watch.
I think the solution described above addresses the requirement but I've read it could cause poor performance. So, is it the best solution? Do I have others alternatives ?
You may find that performance won't be an issue, 100 bindings isn't too bad. If you do need another solution though, you could put an ng-change listener on all the forms that want to watch, like so:
<input type="text" ng-change = "hideTheThing = true">
<div ng-hide = "hideTheThing"></div>
A lot of things that you think you need $scope.$watch for can and should probably be solved with an ng-change.
<input type="text" ng-change="formFieldChanged()">
Inside the function you can do whatver you like with other scope variables.
Hoping to re-create some of the functionality that's available to us in Angular 1.3.X -- the app I am creating has to work well (or at least well-enough) in IE 8. For that reason, I am (sadly) constrained to not using 1.3.X. I've been running into some trouble trying to emulate the $ng-touched attr that is available in 1.3.X.
One part of our app needs to alert users that their form element is invalid if they've tab-bed through it. As it stands, it doesn't set the $invalid attr on any form elements unless I've entered in text and deleted it. I tried using $pristine and $dirty to achieve $invalid after tabbing through, but they both seem to act based on the input's value, not whether it's been touched (maybe this was one of the big advantages of 1.3.X)
Goal: when a user tabs through a form, validations can be fired and set each empty form element as $invalid if it's blank. Basically to emulate the behavior of the $ng-touched attr in 1.2.X. Here's what I have so far:
angular.module('goodStewardApp')
.directive('chf-validate', function () {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
$(elm).blur(
function(elm) {
ctrl.$setValidity(elm, false);
}
);
}
};
});
Any help would be greatly appreciated. Thanks!
Turns out the best way to accomplish emulating the behavior of ng-touched in angular 1.2.x is to use ngBlur to set a validation attribute to be true. So:
<form name="aForm">
<input name="foo" ng-model="foo.bar" ng-blur="validateThisElement=true" ng-required="true">
<div ng-show="aForm.foo.$error.required && validateThisElement">
Oh no! An alert!
</div>
</form>
This allows you to run a validation after a user tabs through your form, a common way that people used to using computers will use to interact with your angular form/app. Hope this helps anyone still stuck w/ 1.2.X for IE8 reasons!