Angular radio button validation with an ng- repeat - angularjs

I'm running into an interesting Angular validation issue. I need to make sure that radio buttons are selected (they might not have a default value when loaded). The values for the radio buttons are iterated over from an array using ng-repeat. This whole thing also happens inside another ng-repeat for a list of users.
The issue is that I have to set a unique/dynamic name attribute on each group of related radio buttons, otherwise selecting one will unselect others in a different row. The validation in based on the name attribute and I cannot seem to find a way to use this unique/dynamic name in the needed ng-class and ng-show expressions.
This is waht is not working:
ng-show="userFormRow.service-{{$index}}.$invalid"
Here's a sample of the code in context:
<table class='table table-striped table-bordered'>
<tbody>
<tr ng-repeat="u in users"
ng-form="userFormRow">
<td>
<!-- THIS is having an issue determining the name of this form item since I need to generate a dynamic one here-->
<div class="form-group"
ng-class="{'has-error': userFormRow.service-{{$index}}.$invalid }">
<label class="control-label center-block">Service</label>
<div class="radio-inline" ng-repeat="o in serviceOptions">
<label>
<!-- HERE is where I define the unique name attribute based on the index of the table repeater -->
<input type="radio"
name="service-{{$parent.$index}}"
value="{{::o}}"
ng-model="u.Service"
ng-required="!u.Service"> {{::o}}
</label>
</div>
<!-- THIS is having an issue determining the name of this form item since I need to generate a dynamic one here-->
<p class="help-block" ng-show="userFormRow.service-{{$index}}.$invalid">A service must be selected!</p>
</div>
</td>
</tr>
</tbody>
</table>
And here is a full code example.http://codepen.io/chrismbarr/pen/eNoGLJ?editors=101 Check the console for errors

You should use bracket notation to access variable object property:
ng-show="userFormRow['service-' + $index].$invalid"
and same with ngClass:
ng-class="{'has-error': userFormRow['service-' + $index].$invalid }"
Demo: http://codepen.io/anon/pen/rVbYpG?editors=100

Related

Values are duplicated into all input field which is created using the ng-repeat and ng-model

I am using the ng-repeat to create the input fields dynamically, everything seems to be working fine and the input fields are created but due to some reason when I enter some value into that created input field then due to two-way data binding the value is entered simultaneously in all the text fields that were created.
As per my knowledge, I am assigning the different ng-model to each of the created fields so I am not sure why the values are being copied. When I try to print the values which are assigned to the input field just above the field then I see the id is different wanted to know why all the fields are taking the same value and also how can I prevent it.
HTML Code:
<tr>
<td ng-repeat="extension in ExtensionList">
<!-- Here the value displayed are different -->
{{ formdata.extension.ExtensionVlaues }}
<input type="text" class="form-control" id="extension.ExtensionVlaues" ng-model="formdata.extension.ExtensionVlaues">
</td>
</tr>
Here is the screenshot from the front-end:
Here is the example of my ExtensionList: {"Field1":"","Field2":"","Field3":1,"ExtensionVlaues":2}
As per my knowledge, the given ng-model is different but still not working. Can anyone please help me with this? I tried few things like ng-model="formdata.extension[ExtensionVlaues]" but still no luck.
I tried to assign ng-model like this but it is not working:
ng-model="formdata.extension[ExtensionVlaues]"
Based on the below answer I tried 2 different things it but it's not working and getting the same issue. Please let me know how can I resolve this:
<td ng-repeat="(key, extension) in ExtensionList">
<input type="text" ng-model="formdata.extension.key">
</td>
<td ng-repeat="(key, extension) in ExtensionList">
<input type="text" ng-model="formdata.extension.ExtensionVlaues">
</td>
You are trying to use ExtensionList as an array. You need to use it as an object with ng-repeat:
<td ng-repeat="(key, extension) in ExtensionList">
<input type="text" ng-model="formdata[extension][key]">
</td>
<td ng-repeat="(key, extension) in ExtensionList">
<input type="text" ng-model="formdata[extension][ExtensionVlaues]">
</td>
Just incase anyone else also struck at this issue:
<span ng-repeat="(key, extension) in ExtensionList" class="form-inline">
<br/>
<span>
{{ extension.NameSpace + ":" + extension.LocalName }}
</span> 
<input type="text" class="form-control" id="extension.ExtensionVlaues" ng-model="ExtensionList.extension[key].FreeText" ng-blur="ExtensionText(ExtensionList.extension[key].FreeText, extension.ExtensionVlaues)">
</span>

angularjs radiobutton groups having its own model

I want to create a a 3 radio button groups each having its own unique model using one ng-repeat. How can I achieve this?
<div class="radio" data-ng-repeat="item in selItem.items" >
<label class="control-label">
<input type="radio"
data-ng-value={{item.vm}}
data-ng-model="????"
name="{{selItem.Title}}"/>{{item.dm}}
</label>
</div>
First and foremost, why would you do that? Radio buttons are for a unique selection among a group of options, so having the same model for all radio buttons is the way to go.
However, for setting unique ng-models for each item iteration inside ng-repeat, you have to use object bracket notation, using $index or a property of each iteration itself to name the property of the object model.
<div ng-repeat="item in items">
<input type="text" ng-model="myModel[item.name]" >
</div>
check this fiddle to see it working

Angular Form Validation inside ngRepeat

I have a series of table rows with various inputs inside of an ng-repeat and I'm trying to use angular's built in form validation to handle required fields. Everything works well except for when I delete one of the items in the array that is backing the ng-repeat.
Here is how I've set up my validation
<td ng-class="{ 'has-error' : vm.testForm.itemName{{$index}}.$invalid }">
<input type="text"
name="itemName{{$index}}"
class="form-control"
ng-model="item.name"
required />
<div class="help-block"
ng-show="vm.testForm.itemName{{$index}}.$invalid"
ng-messages="vm.testForm['itemName'+$index].$error">
<span ng-message="required">Name is required</span>
</div>
</td>
Plunker showing my issue
https://plnkr.co/edit/Q1qyqlSG69EXR2lTrsHk
In the plunker, if you delete the first table row, you'll notice that while the last row is still invalid, the errors have become attached to the row above. Then as you fill in the last row to make it valid and then empty it again, the errors still show up on the wrong row. Deleting subsequent rows just moves the errors further from the actual invalid row until they don't appear on the table at all.
Is there another way I should be going about validating these inputs?
The problem is that you you don't usally use {{}} (interpolation) in built in angular directives. So change your code to:
<td ng-class="{ 'has-error' : vm.testForm['itemName' + $index].$invalid }">
<input type="text"
name="itemName{{$index}}"
class="form-control"
ng-model="item.name"
required />
<div class="help-block"
ng-show="vm.testForm['itemName' + $index].$invalid"
ng-messages="vm.testForm['itemName'+$index].$error">
<span ng-message="required">Name is required</span>
</div>
</td>
Change:
vm.testForm.itemName{{$index}}.$invalid
To:
vm.testForm['itemName' + $index].$invalid
Made a plunker to verify:
https://plnkr.co/edit/vuQiH4D8qUY9jVoThnCy?p=preview

Multiple sets of radio button with ng-model and ng-repeat

I'm very new to Angular and I have some issues with setting the default option on my radio buttons. I have already checked the other answers and using $parent does not solve my issue or I'm using it wrong.
I have a group of radio button which contains 2 input:
input type="radio" name="#{{ form.form_id }}_#{{ $index }}" ng-model="$parent.field.field_data.suggested" value="#{{ field.field_data.value_a}}" > #{{ field.field_data.value_a }} <br>
input type="radio" name="#{{ form.form_id }}_#{{ $index }}" ng-model="$parent.field.field_data.suggested" value="#{{ field.field_data.value_b }}"> #{{ field.field_data.value_b }}
If the page displays only 1 group(pair) of radio button, it correctly sets the default value for the radio button group. The issue here is, when there are 3 groups (3 pairs) of radio button generated by ng-repeat, it only sets the value of the last group of radio buttons and the other 2 groups are left unchecked or blank.
Is this because the radio buttons are generated using 2 ng-repeats? To help, here is my code.
I have an array $scope.filtered_forms which is set by:
$scope.filtered_forms[index] = {
form_id:id,
fields:[{
field_data: {field.label,
field_suggested:string,
value_a:string,
value_b:string},
field_type: radio
},{
field_data: {field.label,
field_suggested:string,
value_a:string,
value_b:string},
field_type radio
},{
...same input as above each object represents a group of radio
}]
}
Basically, $scope.filtered_forms contains form objects. In my html file, I have this:
<div ng-repeat="form in filtered_forms" id="#{{ form.form_id }}">
<table class="table" id="borderless">
<tr ng-repeat="field in form.fields">
<th scope="row" width="35%">#{{ field.field_data.label }}</th>
<td>
<div ng-if="field.field_type == 'radio'" style="margin-bottom: 10px">
<input type="radio" name="#{{ form.form_id }}_#{{ $index }}" ng-model="$parent.field.field_data.suggested" value="#{{ field.field_data.value_a}}" > #{{ field.field_data.value_a }} <br>
<input type="radio" name="#{{ form.form_id }}_#{{ $index }}" ng-model="$parent.field.field_data.suggested" value="#{{ field.field_data.value_b }}"> #{{ field.field_data.value_b }}
</div>
</td>
</tr>
/table>
This right here produces 2 groups/pairs of radio buttons but only the last group gets a default value. Even when using ng-checked and even without $parent.
Additional info, field_suggested has the same value as value_a or value_b. You can see that the radio button is under 2 ng-repeats. I'm using laravel blade and this html file is inside a modal. I removed some of the html data and property inside the form which does not relate to the issue.
Any help is appreciated.
Thanks!
You seem to have mixing many things. I copied your code created a plunker and found that the name for the radio group is not actually form_id_{{$index}} but it has whole object as string. I have changed the code hope it helps you.
See the code here
The issue is with your group names why are you using # in the names. Please remove them it should work fine. Also please see that there are no special characters in the value for name attribute.
name="{{ form.form_id }}_{{ $index }}"

Using multiple ng-models in a single ng-repeat

I'm trying to get multiple values selected form a checkbox list generated using ng-repeat in anguler
<div ng-repeat="item in items">
<input type="checkbox" ng-model="model.ID" ng-true-value="'{{item.ID}}'" ng-false-value="''"/>{{item.Name}}
</div>
But what I want is to have different ng-models for different check boxes. How can I do that. Is there a way to do what ng-repeat does with out using ng-repeat
In Angular one checkbox is linked with one model, but in practice we usually want one model to store array of checked values from several checkboxes.
Checklist-model solves that task without additional code in controller. examples
use $index as key
<div ng-repeat="item in items">
<input type="checkbox" ng-model="model[$index].ID"/>{{item.Name}}
</div>
or use item unique id:
<div ng-repeat="item in items">
<input type="checkbox" ng-model="model[item.ID]"/>{{item.Name}}
</div>

Resources