$valid inside ng-repeat in AngularJS - javascript

I know how to show errors in angular js in case the all form input are invalid. I also know how to show message if one field is invalid.
The Question is how to show a message inside ng-repeat of items, when only some of the items are invalid.
<form name=form>
<div ng-repeat="item in items">
<textarea ng-model="item.value" name="item">
<div ng-show="form.name.$invalid">
I want to show this message if this textarea is invalid
</div>
</div>
<div ng-show="form.$invalid">You have error in your form</div>
</form>
Please see this above line <div ng-show="form.name.$invalid"> it will show the message x times, but I want to show the invalid message only for the invalid input.

Wrap everything under the ng-repeat with a <div> that has ng-form.
ngForm
Nestable alias of form directive. HTML does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a sub-group of controls needs to be determined.
https://docs.angularjs.org/api/ng/directive/ngForm

Related

Template reference variable undefined in radio buttons

I am having troubles with aplying validations on radio buttons in angular, on other input types, i usualy just create the #templateRefVariable on the input and can then access the NgControl that allows me to use things like the touched property of the control.
What im trying to achieve currently is setting the touched property of the div acording to if any of the radio buttons in the group were touched. (seting it in the div because of css dependencies if it is not in that outer div the validations will not show), but typeCode is always undefined.
<div class="form-group">
<label>Label</label>
<div class="btn-group btn-group-toggle w-100"
[class.ng-invalid]="!viewmodel.typeCode"
[class.ng-touched]="typeCode?.touched">
<label *ngFor="let domain of types" class="btn btn-toogle"
[class.active]="domain.code==viewmodel.typeCode">
<input type="radio" [(ngModel)]="viewmodel.typeCode"
#typeCode="ngModel" name="typeCode"
[value]="domain.code">
{{domain.description}}
</label>
</div>
<validation-message *ngIf="!viewmodel.typeCode"
[message]="'Required'"></validation-message>
</div>
With invalid i can workarround it by using the information in the view model to see if it was set already but the information on touched is not in the view model.
And i cant do the same for ng-touched because i need to set touched when there is an atempt to submit the form (even if the inputs were not actualy touched).
Any idea why typeCode (templateVariableRef) is undefined while using it in radio buttons ? i suspect it might be because of there being multiple in the page but i am not sure.
P.S: Using template driven forms
StackBlitz as requested (note errors on console because of typeCode undefined):
https://angular-5vqi5c.stackblitz.io
It is because ngFor is a structural directive and creates a nested template, and therefore these template variable(s) are out of scope.
Would moving your logic inside the ngFor be an option for you e.g.?
<div class="btn-group btn-group-toggle w-100"
[class.ng-invalid]="!viewmodel.typeCode">
<ng-container *ngFor="let domain of types">
<div [class.ng-touched]="typeCode?.touched>
<label class="btn btn-toogle"
[class.active]="domain.code==viewmodel.typeCode">
<input type="radio" [(ngModel)]="viewmodel.typeCode"
#typeCode="ngModel" name="typeCode"
[value]="domain.code">
{{domain.description}}
</label>
</div>
</ng-container>
</div>
PS. I haven't tested the code above.

Angular JS ng-form Email validation before the data binding

I have an Angular JS form as below:
<div ng-controller="EmpController as empVm"
name="formEmployee" ng-form >
<div>
<div class="col-sm-5">
Email
</div>
<div class="col-sm-7">
<input type="email" validate-length ng-maxlength="2000"
ng-model="empVm.profileData.email" name="email"
ng-pattern="^[_a-zA-Z0-9]+(\.[_a-zA-Z0-9]+)*#[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,4})$"/>
<div ng-show="(formEmployee.email.$dirty || formEmployee.email.$touched) && formEmployee.email.$invalid">
<span ng-show="!formEmployee.email.$error.pattern">Invalid Email</span>
</div>
</div>
</div>
</div>
Even though the email field has the valid email the form is always invalid. Once I interact with the email text box like changing some text in the email text box the form is becoming valid again.
What I am trying to achieve is, the form should validate data for the email text box once the value is bind from the service call and form should be valid after the page load if it is valid email else form should be invalid and the above div which has the invalid email message should appear.
The span specifying Invalid Email is not closed.
The value in the ng-pattern should be an $scope/vm object or a raw string (i.e. between quotes).
The email pattern does not seem to be complete.
In your example, we don't know where frmAgentProfile comes from.
You are talking about a service call, we don't have any informations about that. If you want to validate from a service call, you should create a custom async validator.
I pushed your code in a fiddle where the ng-pattern works.
HERE
Data coming from the back end service call had a space character at the end of the email for which the regex failed and that space was not visible in the text box on UI and that's the reason why the form was becoming invalid.

Angular1: How to reflect ng-model errors on another element?

I have a directive with the following template
<div>
<span class="label">My Label</span>
<input ng-model="name" required>
</div>
I want the label to be painted red when the input field is invalid.
How can I do that?
Currently I have another directive to sync all the errors from ngModelCtrl to the wrapping div
<div add-all-errors>
...
</div>
And the directive's link function does something like this:
const ngmodel = $element.find('[ng-model]').controller('ngModel');
$scope.$watch(()=>ngmodel.$error, addAllClasses, true);
Where addAllClasses simply makes sure the correct classes appear on the element..
I also tried just adding the same ng-model
<div ng-model="name">
...
</div>
But did not see the classes there..
any better way to do this?
This is why we use the angularjs form... I'm really not sure why people are against using a very handy feature.
I've made a plunker for you.
https://plnkr.co/edit/bGOcQjWzlRq2aTYZUYNm?p=preview
<form name="form">
<span ng-class="{red: form.name.$invalid}">Name:</span>
<input name="name" ng-model="name" required>
</form>
A little more insight of what's going on. form is added to the scope auto magically by angularjs by it's name. In this case, I named it form, however it can be any name.
Now form is an ngForm Object and adds all input field into it by their name attributes. This way we can do form.name to get another object similar to the ngForm Object. We can then use $invalid or $valid properties with ng-class.
ngForm is pretty powerful and is loaded with many cool properties and methods. Just call console.log(scope.form); You will need to put in a method and add it to ng-change to see updates.

ngMessages not working correctly with nested input

I have an input field that is nested within another <div> element, and I am trying to use ngMessages on that inside input field, but I can't seem to get it to validate correctly.
<div class="form-group" ng-model="object.idnumber" ng-hide="condition.userObjectsHidden">
<label class="form-control-label col-lg-12">ID Number</label>
<div class="col-lg-12">
<input type="text" name="idnumber" placeholder="111001111"
ng-model="user.idnumber"
ng-pattern="idpattern"
class="form-control input-lg"
required="required"></input>
<div ng-messages="idnumber.$error" ng-if="idnumber.$dirty">
<p ng-message="pattern">You are wrong!</p>
</div>
</div>
</div>
I'm not sure if it matters in terms of functionality where the <div ng-messages...> tag is, but I have also tried having it completely outside of this element with the same results. If I understand Angular and ngMessages correctly, I need to assign ng-messages to a directive--$error in this case--that I get to by dot-walking across name assignments. As far as I know, I have done this with idnumber.$error, although to be fair, I have also tried a more extensive dot-walk by using kiosk-form.uin.$error, where kiosk-form is the name of the entire form.
I have tried both ng-message="pattern" as well as ng-message="required". Also, just for clarity, idpattern is defined in my Javascript file as a regex string. It is defined correctly.
Rename your form as kioskFormand then ng-messages ="kioskForm.idnumber.$error"

angular required message on $error.required OR (pristine AND empty value)

I have searched for a solution all over, so here is my first question to this site:
I am trying to have some nice validation in angular (ionic) page where the logic is I want to show a "Required" message under label when either there is a validation error ($error.required) OR the field has not been touched and is empty (like a first time load). I can use pristine to check if it is not been modified, but if the form loads values from the model subsequently (like when restoring from localstorage), it still shows the "required" validation message.
I have tried the following:
<form name="wdform" novalidate>
<label class="item item-input item-stacked-label">
<span class="input-label green-small">ID</span>
<div class="validation" ng-show="wdform.userid.$error.required ||
(wdform.userid.$pristine && wdform.userid.length < 1)" >
Required
</div>
<input name="userid" ng-model="input.UserID" type="text" required>
</label>
... rest of form...
</form>
Also have tried:
<div class="validation" ng-show="wdform.userid.$error.required ||
(wdform.userid.$pristine && input.UserID.length < 1)" >
and various other permutations such as:
(wdform.userid.$pristine && input.UserID == '')
(wdform.userid.$pristine && wdform.userid.$invalid)
etc. ad nauseum.
On a separate but related note, I have also found that the built in validation is pretty brittle when it comes to form and field names... it only seems to work at all if the form name is only lowercase and/or contains no special characters ("DumbForm" and "dumb-form" fails, but "smartform" works).
Anyway, does anyone have any thoughts?
I feel like your two scenarios, (1) $error.required and (2) pristine and empty, might be redundant. Anytime #2 would be true, so would #1. I think you could use just #1.
Look at this example:
http://plnkr.co/edit/PgQ3vEIOKkfA38dDWjhp?p=preview
<body ng-controller="myController as vm">
<h1>Hello Plunker!</h1>
<form name="wdform">
<input type="text" name="userid" ng-model="userId" required/>
<div ng-show="wdform.userid.$error.required">Required</div>
</form>
</body>
However, it sounds like you are populating your form on page load some times from localStorage and somehow this is not causing the $error.required property to be changed to true, but it should. So your real problem I think lies in need to call $scope.$apply() or something to tell angular to run validations again.
I found that the issue was related to where the validation div was placed.
If the validation div was placed before the input field (so that it displayed the validation message beneath the field label), I encountered the error specified in this question.
By placing it after the input tag, it works as expected (with the validation message beneath the input field).
I would consider this a bug either in Angular or Ionic. Hopefully it will be corrected in the upcoming version 2 of both.
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="f3.form.reset()">
Just add the click in the button.so form loads values from the model in reset().Once click the button form will reset. You get new form with no errors.

Categories

Resources