How to validate inputs dynamically created using ng-repeat, ng-show (angular)
I have a table that is created using ng-repeat. I want to add validation to each element in the table. The problem is that each input cell has the same name as the cell above and below it. I attempted to use the {{$index}}
value to name the inputs, but despite the string literals in HTML appearing correct, it is now working.
Here is my code as of now:
<tr ng-repeat="r in model.BSM ">
<td>
<input ng-model="r.QTY" class="span1" name="QTY{{$index}}" ng-pattern="/^[\d]*\.?[\d]*$/" required/>
<span class="alert-error" ng-show="form.QTY{{$index}}.$error.pattern"><strong>Requires a number.</strong></span>
<span class="alert-error" ng-show="form.QTY{{$index}}.$error.required"><strong>*Required</strong></span>
</td>
</tr>
I have tried removing the {{}}
from index, but that does not work either. As of now, the validation property of the input is working correctly, but the error message is not displayed.
Anyone have any suggestions?
Edit: In addition to the great answers below, here is a blog article that covers this issue in more detail: http://www.thebhwgroup.com/blog/2014/08/angularjs-html-form-design-part-2/
Since the question was asked the Angular team has solved this issue by making it possible to dynamically create input names.
With Angular version 1.3 and later you can now do this:
<form name="vm.myForm" novalidate>
<div ng-repeat="p in vm.persons">
<input type="text" name="person_{{$index}}" ng-model="p" required>
<span ng-show="vm.myForm['person_' + $index].$invalid">Enter a name</span>
</div>
</form>
Demo
Angular 1.3 also introduced ngMessages, a more powerful tool for form validation. You can use the same technique with ngMessages:
<form name="vm.myFormNgMsg" novalidate>
<div ng-repeat="p in vm.persons">
<input type="text" name="person_{{$index}}" ng-model="p" required>
<span ng-messages="vm.myFormNgMsg['person_' + $index].$error">
<span ng-message="required">Enter a name</span>
</span>
</div>
</form>
AngularJS relies on input names to expose validation errors.
Unfortunately, as of today, it is not possible (without using a custom directive) to dynamically generate a name of an input. Indeed, checking input docs we can see that the name attribute accepts a string only.
To solve the 'dynamic name' problem you need to create an inner form (see ng-form):
<div ng-repeat="social in formData.socials">
<ng-form name="urlForm">
<input type="url" name="socialUrl" ng-model="social.url">
<span class="alert error" ng-show="urlForm.socialUrl.$error.url">URL error</span>
</ng-form>
</div>
The other alternative would be to write a custom directive for this.
Here is the jsFiddle showing the usage of the ngForm: http://jsfiddle.net/pkozlowski_opensource/XK2ZT/2/