Angular - Form and $pristine does it work with nested inputs? - angularjs

I have the following form.
A couple of issues I am facing:
1 - I'm unable to check for $pristine on the form with console.log($scope.myFirstForm.$pristine); I'm seeing the error: `cannot read property '$prestine' of undefined'.
Based on my code is this actually possible i.e. to use when the input fields are nested within several div tags?
2 - To clear the fields I'm currently having to do each field individually, is it possible to do at the form level which clears all input fields with that?
<form name="myFirstForm">
<div class="row">
<div class="large-12 medium-12 small-12 columns">
<input ng-model="main.pToAdd" type="text"/>
</div>
</div>
<div class="row homeTopBackgroundColor">
<div class="large-12 medium-12 small-12 columns">
<h5>Room</h5>
</div>
<div class="row large-12 medium-12 small-12 columns">
<input ng-model="main.o1ToAdd" type="text" />
</div>
</div>
<div class="row">
<div class="large-12 medium-12 small-12 columns">
<input ng-model="main.opToAdd" type="text"/>
</div>
</div>
</form>
SOLVED:
In my routes file I was specifying a controller (so 2 controllers on one page). I was checking on the child scope not the parent hence not being found. So I removed the setting of a controller in the routes file and just specified it in required places of HTML.

First the form included in the controller will automatically be in the scope of that controller.
Inputs inclosed in the form are part of the form no matter how nested it is. (use the name attr to be able to validate them.. assign errors and states to them)
Setting the form to pristine state will clear even the validations .. setting the main object in your case to {} will clear all the input fields.
`cannot read property '$prestine' of undefined -> can be because you are calling it in the controller before the form is assigned in the view. try the same thing on a click of any button should not give the same answer.

Related

Angular ng-show is not executing with ng-message tag

Not sure what I am doing wrong here.
I want to display an ng-message after the user submit the form. However , the message is shown when the form is rendered. It seem like the ng-show is not evaluating.
I printed the field in the expression and it is false when I open the form. Also, I change it to ng-hide but I have the same issue.
Can you please have a look ..
<div class="small-12">
<label>first name
<span class="field-error"> *</span>
</label>
<input name="firstName"
type="text"
maxlength="25"
ng-disabled="isSubmitting" required
ng-model="candidate.firstName"
ng-class="{error:isFormSubmitted && contactForm.firstName.$error.required}" />
<div ng-messages="forms.contactForm.firstName.$error"
class="errorFormLabel" role='alert'>
<div ng-message="required"
ng-show="isFormSubmitted">This is a required field {{isFormSubmitted}}
</div>
</div>
</div>
Think about ng-messages as a switch clause, you can nest the /ng-show/ng-hide inside ng-message directive but not use them together
For example:
<div ng-messages="forms.contactForm.firstName.$error"
class="errorFormLabel" role='alert'>
<div ng-message="required">
<span ng-show="isFormSubmitted">This is a required field {{isFormSubmitted}}</span>
</div>
</div>
</div>
If you don't want an extra element: <span>, try ng-if, basically ng-if has the priority higher than any other angularjs directive and it will force the ng-message directive to be removed from the DOM tree if the expression is not positive.
<div ng-message="required"
ng-if="isFormSubmitted">This is a required field {{isFormSubmitted}}
</div>

Validate form using dynamically textarea name

I have one validation form using angular. I would like validate forms in ng-repeat using dynamically textarea name. Look on my code:
<div ng-repeat="comment in comments track by $index">
<form name="main.adminArticleReplyForm" novalidate>
<div ng-class="{'has-success':(main.adminArticleReplyForm.commentReply_{{$index}}.$valid), 'has-error':(!main.adminArticleReplyForm.commentReply_{{$index}}.$valid)}">
<textarea name="commentReply_{{$index}}" ng-model="main.commentReply[$index]" required></textarea>
<ul ng-show="(!main.adminArticleReplyForm.commentReply_{{comment.number}}.$pristine && main.adminArticleReplyForm.$error.minlength[0].$viewValue.length)">
<li>You have to add {{10 - main.adminArticleReplyForm.$error.minlength[0].$viewValue.length}} characters</li>
</ul>
<button type="submit">Submit</button>
</div>
</form>
</div>
And my problems:
If you check {{main.adminArticleReplyForm}} commentReply_{{$index}} is always last $index in ng-repeat for example if are 4 comments in array in form always is commentReply_4, but textareas name in DOM are correct.
I have to use controller as, in my case main, but if I remove main from form name, everything works nice.
Summary, {{main.adminArticleReplyForm}} is validate only for last $index in ng-repeat previously $indexes are ignored
Here is fiddle for look that every commentReply_{{$index}} is commentReply_2 https://jsfiddle.net/8od25zhb/5/
Description
you don't need to track it by index that make repeat last index
you don't need to add main to the form, because form is in repeat so make it unique, if you want to have just one form make it out of repeat; so we just use comment.adminArticleReplyForm as form name, and just main.comments used main from controller.
by this 2 step your forms validate just the textarea which inside it.
you don't need create unique names and models for textarea, because you create them inside ng-repeat and all are unique.
<div ng-app="app" ng-controller="ctrl as main">
<div ng-repeat="comment in main.comments">
<form name="comment.adminArticleReplyForm" novalidate>
{{comment.adminArticleReplyForm}}
<div>
<textarea name="commentReply" ng-model="comment.commentReply" required></textarea>
<button type="submit">Submit</button>
</div>
</form>
<hr/>
</div>
</div>
Since, AngularJS default validation works on hierarchy of element names to detect their state thus, the name of textarea you have used is commentReply_{{$index}} with a underscore but you are using commentReply{{comment.number}} in the validation expressions. So make it look with a underscore and it will work. So, final code will look something like this:
<div ng-repeat="comment in comments track by $index">
<form name="main.adminArticleReplyForm" novalidate>
<div ng-class="{'has-success':(main.adminArticleReplyForm.commentReply_{{$index}}.$valid), 'has-error':(!main.adminArticleReplyForm.commentReply_{{$index}}.$valid)}">
<textarea name="commentReply_{{$index}}" ng-model="main.commentReply[$index]" required></textarea>
<ul ng-show="(!main.adminArticleReplyForm.commentReply_{{comment.number}}.$pristine && main.adminArticleReplyForm.$error.minlength[0].$viewValue.length)">
<li>You have to add {{10 - main.adminArticleReplyForm.$error.minlength[0].$viewValue.length}} characters</li>
</ul>
<button type="submit">Submit</button>
</div>
</form>
</div>

How to use ng-repeat in one template taking filter query from another one?

I have an angular app, every state consists of two components: navbar and components under the navbar. In the lower one I use ng-repeat to show some items and I need to use filter:
<div class="col-sm-2 store__item col-centered" ng-repeat="book in vm.books | toArray | orderBy:query" >
...
</div>
However ng-model="query" is in different template, belonging to the navbar component:
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search" ng-model="query">
</div>
</form>
How can I bind them, so that filter would take query from navbar?
Thank you
Few suggestions,
You can keep the model "query" - in the $rootScope so both of your component can access the same model.
Use the angular's event manager, $broadcast/$emit, This is my recommended way, since its follows the decoupled architecture.

AngularJS attempt to show div element based on hidden input value is not working

I can't seem to get my div elements to show based on a hidden input value according to the code below:
<form method="post">
<fieldset data-ng-app="">
<input type="hidden" id="Method" name="Method" value="1" data-ng-model="methodType" />
<div data-ng-show="methodType=='1'">Method 1</div>
<div data-ng-show="methodType=='2'">Method 2</div>
</fieldset>
</form>
None of the div elements are being displayed when the page is loaded. It seems to work when I change the type of the input to "text", but then I had to manually type in the value into the field to get it to show/hide accordingly. May I get help with this?
Angular won't recognise setting the model to a value unless the input is interacted with — such as on a radio button.
If what you are trying to do is to set the model value on load, set it in a controller, or use data-ng-init instead of a hidden input.
<form method="post">
<fieldset data-ng-app="" data-ng-init="methodType = 1">
<div data-ng-show="methodType == 1">Method 1</div>
<div data-ng-show="methodType == 2">Method 2</div>
</fieldset>
</form>

ng-class within ng-repeat having dynamic ng-model

I am iterating over a array of strings with ng-repeat
<div ng-repeat="i in mdsecuritysensorswsize">
in there I have a required select with a 'dynamic model'
ng-model="valueBag[i+'sizes']"
now I want to add a has-error class, if the select is empty (apply bootsrap3 error style)
ng-class="{'has-error': myForm.valueBag[i+'sizes'].$invalid, 'has-success': !myForm.valueBag[i+'sizes'].$invalid}"
But this doesn't seem to work with such a dynamic ng-model name.
Here is the complete code:
<div ng-repeat="i in mdsecuritysensorswsize">
<div class="form-group">
<div class="col-md-2"
ng-class="{'has-error': myForm.valueBag[i+'sizes'].$invalid, 'has-success': !myForm.valueBag[i+'sizes'].$invalid}"
>
<select class="form-control" required
ng-options="resText[j] for j in mdsecuritysensorswsizesizes2"
ng-model="valueBag[i+'sizes']"></select>
</div>
</div>
</div>
Am I missing something here?
this from the comments did the job:
if you create your form inputs dynamically, it will be a problem with this code when you try to access myForm.valueBag[i+'sizes'].$invalid If you create form inputs dynamically, check out my directive to solve this problem here: stackoverflow.com/questions/21455695/… – Khanh TO Feb 3 at 10:04
AngularJS dynamic form field validation
THX #Khanh TO

Resources