How to get a repeat input's value - angularjs

ng-repeat's each item get its own scope, but how to get the input value?
In a normal situation, just set a ng-model and refer it through $scope.
<div ng-repeat="item in items">
<input type="text">
</div>
Is thre a way to work around this?

<div ng-repeat="item in items">
<input type="text" ng-model="item.value">
</div>

Related

Nested Ng-repeat with ng-if passing proper $index

I have a nested ng-repeat with ng-if, inside each ng-if I have a check-box which is containing a ng-click function. I want to pass the nested ng-repeat's $index value through the function.
Here is my code.
<div class="student" ng-repeat="student in studentDetails.childNumber track by $index" ng-init=" studentnumber = $index">
<div ng-repeat="grmnt in student.garmentNumber track by $index" ng-init="grmntidex = $index" ng-if="grmnt.gurmentType === 'shirt'">
<div ng-click="garmentOpen = !garmentOpen;" class="z-depth-1 garmentelement">Garment</div>
<div class="garmentHeader" ng-if="garmentOpen">
<div class="garmentBody">
<div class="row">
<p class="col s6 center-align">
<input type="checkbox" id="BrandMeasurement" ng-click="msrmntSelector(grmnt)" />
<label for="BrandMeasurement">Brand Measurement</label>
</p>
<p class="col s4 center-align">
<input type="checkbox" id="BodyMeasurement" ng-click="msrmntSelector(grmnt)" />
<label for="BodyMeasurement">Body Measurement</label>
<div>
</div>
</div>
</div>
</div>
</div>
</div>
But the problem is when I am selecting the last grmnt element it's passing proper garment with id but after selecting the first element its not passing 2nd or 3rd or 4th any of the garment. In every case it's passing only the first element.
Can any one please tell me where I'm making any mistake (if any)??
Don't use ng-if on the ng-repeat just use a filter in the ng-repeat.
<div ng-repeat="grmnt in student.garmentNumber | filter:{gurmentType: 'shirt'} track by $index" ng-init="grmntidex = $index">
Edit: I think maybe the problem is in your labels. The label's for attribute needs to uniquely match the input's id attribute. Each row needs its own id/for pair. Use $index to do this.
<input type="checkbox" id="BrandMeasurement{{$index}}" ng-click="msrmntSelector(grmnt)" />
<label for="BrandMeasurement{{$index}}">Brand Measurement</label>

$index in ng-class for form validation

I want to validate an angular form input and give it a class if is not $valid, the problem is, it´s inside a ng-repeat looping an array of int, and the input name is based on the $index:
<li ng-repeat="item in selectedItem.data.ax_ch">
<div ng-class="{'has-error':!form.ax_$index.$valid}">
<input type="text" id="ax_{{$index}}" name="ax_{{$index}}" ng-model="item" required=""/>
</div>
</li>
Everything gets the $index in the output, but the ng-class:
<li ng-repeat="item in selectedItem.data.ax_ch">
<div ng-class="{'has-error':!form.ax_$index.$valid}">
<input type="text" id="ax_0" name="ax_0" ng-model="item" required=""/>
</div>
</li>
What I expected it to be:
<li ng-repeat="item in selectedItem.data.ax_ch">
<div ng-class="{'has-error':!form.ax_0.$valid}">
<input type="text" id="ax_0" name="ax_0" ng-model="item" required=""/>
</div>
</li>
I have searched and people have similar problems but none of them have been solved so far. Is there any angular-super-hero-master-plus-advanced who can help me with it :) ?
Because you are constructing the property/key on form dynamically, you do the same thing you would in normal Javascript: use square["bracket"] notation.
Change your markup to:
<li ng-repeat="item in selectedItem.data.ax_ch">
<div ng-class="{'has-error':!form['ax_' + $index].$valid}">
<input type="text" id="ax_{{$index}}" name="ax_{{$index}}" ng-model="item" required=""/>
</div>
</li>

can we append the string with a variable in the ng-model?

<div ng-repeat="data in assets">
<input type="checkbox" ng-model="text"+{{$index}}/>
</div>
here I want to generate different ng-models for each checkbox
You can use alias name "data" and assign "data.isChecked" to ng-model.
<div ng-repeat="data in assets">
<input type="checkbox" ng-model="data.isChecked" />
</div>
This will add that "isChecked" variables at run time to all objects of "assets" array.
It's better to have your models in the array you are looping over.
<div ng-repeat="data in assets">
<input type="checkbox" ng-model="data.input"/>
</div>

How set ngClick only for $first element in ngRepeat?

How can ng-click be assigned to the $first element in ng-repeat? In the below code doSomething() should be called only when the first input is clicked. The remaining inputs shouldn't have ng-click handlers assigned. I've found examples of how to use $first with ng-class or ng-show but not with ng-click.
<div ng-repeat="item in items">
<input type="checkbox" ng-click="doSomething()"/>{{item.name}}
</div>
Try this:
<input type="checkbox" ng-click="$first && doSomething()"/>{{item.name}}
working examlpe: http://jsfiddle.net/wLrYc/
You could also use ngSwitch which avoids creating all the handlers which you mention in your comment to the accepted answer:
<div ng-repeat="item in items" ng-switch on='$first'>
<input type="checkbox" ng-switch-when='true' ng-click="doSomething()"/>
<input type="checkbox" ng-switch-when='false'/>
{{item.name}}
</div>
Semi-ugly solution: send $first as argument to doSomething()
<div ng-repeat="item in items">
<input type="checkbox" ng-click="doSomething($first)"/>{{item.name}}
</div>
and then have $scope.doSomething(actuallyDoSomething) only do it's thing if actuallyDoSomething is true.

How to make angular js hide DOM elements, and not remove them, in filters

Angular ng-repeat with filter works this way (I just discovered it by observing DOM in Chrome's developer tools):
It actually removes the nodes which don't satisfy filter condition and re-renders everything.
See this fiddle example. If you look at the DOM, and see what happens there, you can understand what I mean.
<div ng-app>
<h2>Instant Search</h2>
<div ng-controller="SearchCtrl">
<input type="text" ng-model="filterText" />
<ul>
<li ng-repeat="state in states | filter:filterText">
<label>
<input type="checkbox" ng-model="state.abbreviation">
{{state.name}}
</label>
</li>
</ul>
</div>
</div>
What I need now, is to make angular js hide nodes, not remove them. In other words, when I filter nodes, for example I want to make those nodes which don't satisfy filter condition to have a class of hidden, and I'll hide them via CSS.
ng-show placed on the repeating element will cause them to be hidden: Fiddle http://jsfiddle.net/NAumK/19/
http://docs.angularjs.org/api/ng.directive:ngShow
<div ng-app>
<h2>Todo</h2>
<div ng-controller="TodoCtrl">
<input type="text" ng-model="filterText" />
<ul>
<li ng-repeat="state in states" ng-show="state.name.indexOf(filterText) != -1">
<label>
<input type="checkbox" ng-model="state.abbreviation">
{{state.name}}
</label>
</li>
</ul>
<input type="text" ng-model="textFilter" />
</div>
</div>
Filters remove elements as does the ng-if and ng-switch directives. You can also use css coupled with the ng-class directive to hide the elements however I recommend sticking with the ng-show for clarity. One further note of caution, hiding as opposed to removing elements makes the test cases harder to prove. You can have collisions with classes that display incorrectly but still pass (Selenium) tests.
You can use ng-show or ng-hide instead of filters.
You cannot use filter in ng-repeat because it filters the actual array that ng-repeat receives. You'll have to implement your own "filtering" logic.
I'd do it using a conditional ng-class, like this:
<li ng-repeat="state in states" ng-class="{'hidden': isHidden(state)}">
<label>
<input type="checkbox" ng-model="state.abbreviation">
{{state.name}}
</label>
</li>
$scope.isHidden = function(state) {
if(state.name.toLowerCase().indexOf($scope.filterText.toLowerCase()) < 0) {
return true;
}
return false;
}
I thinks that one answer would be like this
<div ng-app>
<h2>Instance Search</h2>
<div ng-controller="SearchCtrl">
<input type="text" ng-model="filterText" />
<ul>
<li ng-repeat="state in states"
ng-show="state.name.tolowerCase().indexOf(filterText.toLowerCase()) != -1">
<label>
<input type="checkbox" ng-model="state.selected">
{{state.name}}
</label>
</li>
</ul>
</div>
</div>
Just replace filter with:
ng-show="([state] | filter:filterText).length > 0"

Resources