AngularJS: $index lost with filter? - angularjs

I'm new to AngularJS so please be kind to me.. :-P
So I'm looping twice with ng-repeat as in this example:
<ul>
<li ng-repeat="b in aMSG">
<p>{{b.name}}</p>
<ul>
<li ng-repeat="c in b.x"><a ng-click="getM($parent.$index,$index)" href="#">{{c.name}}</a></i>
</ul>
</li>
</ul>
See the fiddle: http://jsfiddle.net/trK98/
But when I apply a filter to search for text within the children:
<ul>
<li ng-repeat="b in aMSG">
<p>{{b.name}}</p>
<input type="text" ng-model="search" placeholder="Search for?">
<ul>
<li ng-repeat="c in b.x|filter:search"><a ng-click="getM($parent.$index,$index)" href="#">{{c.name}}</a></i>
</ul>
</li>
</ul>
The $index is lost as you can see here: http://jsfiddle.net/zb2kc/
(search for instance for juice then click on it you'll see $index = 0)
What am I doing wrong?
Thank you!
P.S: Sorry for my poor english.

Never use $index for any kind of logic. It can be used for managing CSS classes only. It's a highly volatile variable and will be changed after any change in source array (deletion, re-ordering), so $index is not bind to element of array, but only to position of some element in current view rendering.

Related

How to auto select the first element with ng-repeat in angular?

Could you please help me to auto select the first item for the menu on the left.
here is my code : https://next.plnkr.co/edit/4pGTMsVlSiFo7eoS?preview
Like this:
<div class="floatingbox list">
<input type="text" ng-model="check" placeholder="search applets"
ng-init="setSelectedModel(model[0])">
<ul>
<li ng-repeat="model in model | filter:check">
<a class="listItem" href ng-click='setSelectedModel(model)'>{{model.key}}</a></li>
</li>
</ul>
</div>
Notice the ng-init="setSelectedModel(model[0]) that selects the 1st item on page load by calling the same function that would be used when clicked on a certain item.
If I read what you wanted correctly.

AngularJS - Change scope with one of the iterations of a ng-repeat

I have a project with Angular where I don't want to use a select element with ng-options, so I made up a list with different options in order to select one of them.
<div class="countrylist">
<ul>
<li ng-repeat="c in shippingCountry"><p>{{c.name}}</p></li>
</ul>
</div>
So the option selected would modify another element where the chosen option would be displayed.
<div>
<ul>
<li>{{selectedCountry}}</li>
</ul>
</div>
In order to do that, I would need to pass the data from the chosen option of the first element into the 2nd one. I have tried doing something like this
<li ng-repeat="c in shippingCountry" ng-click="selectedCountry = {{c}}"><p>{{c.name}}</p></li>
with no success.
You can check the plunker here Thanks in advance
I suggest you to use a function over there like this in the DEMO
<li ng-repeat="c in shippingCountry" ng-click="Click(c)"><p>{{c.name}}</p></li>
Having this method in your controller
$scope.Click=function (c)
{
$scope.select=c;
}
It creates child scope for each iteration, so explicitly refer parent scope:
Change like this,
<ul>
<li ng-repeat="c in shippingCountry" ng-click="$parent.selectedCountry = c"><p>{{c.name}}</p></li>
</ul>
DEMO
I've fixed your plunker here. It would be better to use methods in scope for this operations because they work in current scope, not in child
<li ng-repeat="c in shippingCountry" ng-click="selectCountry(c)">
<p>{{c.name}}</p>
</li>
// .html
<div>
<ul>
<li>{{selectedCountry.item}}</li>
</ul>
</div>
<div class="countrylist">
<ul>
<li ng-repeat="c in shippingCountry" ng-click="selectedCountry.item = c"><p>{{c.name}}</p></li>
</ul>
</div>
// controller
$scope.selectedCountry = {
item: $scope.shippingCountry[0]
};
Example

access variable in scope from ng-repeat ng-style

I got some problem on AngularJS.
my controller, mainCtrl, has this variables :
this.colors = {Sam:blue,Jane:red,Tom:pink};
this.arr = [{person:'Sam',story:'some story'},{name:'Tom',story:'some story2'}]
And I got this code :
<div ng-controller="mainCtrl as vm">
<ul ng-repeat="obj in arr">
<li ng-style={color:vm.color[obj.person]}>{{obj.story}}</li>
</ul>
</div>
I want that the li will be colored such as the color of the person at colors dictionary . how can I handle that? I got undefined every time, but when I do it explictly its work , for Example :
<li ng-style={color:vm.color['Sam']}>{{obj.story}}</li>
You are using the controllerAs-Syntax, so you must use vm.arr in your ng-repeat. And furthermore you should use the ng-repeat on the list item:
<ul>
<li ng-repeat="obj in vm.arr" ng-style="{color:vm.color[obj.person]}">{{obj.story}}</li>
</ul>
It should look like this.
<div ng-controller="mainCtrl as vm">
<ul>
<li ng-repeat="obj in vm.arr track by $index"
ng-style="{'color':vm.colors[obj.person]}"
ng-bind="obj.story">
</li>
</ul>
</div>
Remember to use your alias vm (controllerAs)
Usetrack by with ng-repeat for better performance.
I think that ng-repeat should have been placed in li
Her's a working jsfiddle http://jsfiddle.net/irhabi/nh4ddemr/

How to iterate through an array of arrays in JSON using ng-repeat?

I am trying to iterate over a JSON object userTypes.
For the below code:
In the 1st ng-repeat:
{{user.type}} outputs 'Parent'(as expected),
{{user.options}} outputs '[{"option1":"11QWERT","option2":"22QWERT"}]'(as expected).
But in the 2nd ng-repeat, I am not able to iterate through the user.options and output each of the {{options}}
What should be changed to get the option1 and option2 as the outputs in 2nd ng-repeat ?
JS snippet
var userTypes = [{
"type": 'Parent',
"options": [{
"option1": "11QWERT",
"option2": "22QWERT"
}]
}]
HTML snippet
<li ng-repeat="user in userTypes">
<p>{{user.type}}</p>
<p>{{user.options}}</p>
<li ng-repeat="option in user.options">
<p>
{{option}}
</p>
</li>
</li>
Replace your child <li> with <ul> and then you can iterate user.options like so:
<li ng-repeat="user in userTypes">
<p>{{user.type}}</p>
<ul ng-repeat="(key, value) in user.options[0]">
<p>{{key}}: {{value}}</p>
</ul>
</li>
Or if your options may include more then one object:
<li ng-repeat="user in userTypes">
<p>{{user.type}}</p>
<ul ng-repeat="option in user.options">
<li ng-repeat="(key, value) in option">{{key}}: {{value}}</li>
</ul>
</li>
If you don't need object keys:
<ul ng-repeat="option in user.options">
<li ng-repeat="item in option">{{item}}</li>
</ul>
Fiddle
Extended explanation:
In your example you have <li> tag inside another <li>:
<li ng-repeat="user in userTypes">
<li ng-repeat="option in user.options">
</li>
</li>
Since it is not a valid HTML browser will interprets this markup to following:
<li ng-repeat="user in userTypes">
</li>
<li ng-repeat="option in user.options">
</li>
Since ng-repeat creates new scope for each iteration you can't access user variable in second ng-repeat and iterator wouldn't run.
For this exact JSON input it should be like this:
<li ng-repeat="option in user.options">
<p>
{{option.option1}}
{{option.option2}}
</p>
</li>
However as you said you want non fixed number of options, update your JSON to be like this:
"options":["11QWERT","22QWERT"]
And then your code should work as you wanted it.
You can add each new element to list with simple coma before it.
Since user.options is an array you should loop it again. By doing that you will get an object, with that object you can access your options1 and option2 easily.
please refer working plunker:
http://embed.plnkr.co/5c3i5fY50jLP0fFgxkUX/preview
see through the code if you have any doubt.
Hope this helps
A little aside, but just found out you can render a valid list HTML using ng-repeat-start/end in combination with ng-if="false" for the given array of arrays to flatten them:
<ul>
<script ng-repeat-start="user in userTypes" ng-if="false"></script>
<li ng-repeat="item in user.options">{{item}}</li>
<script ng-repeat-end="" ng-if="false"></script>
</ul>
Just access the propertie of the option object in the second ng-repeat. Like option.option1
You should probably make your user.options an object and not an array containing a single object.
Note the difference between these:
[{"option1":"11QWERT","option2":"22QWERT"}]
{"option1":"11QWERT","option2":"22QWERT"}
You can then iterate the options with an ng-repeat like discussed here:
<li ng-repeat="(key, value) in user.options">
<p>{{ key }}: {{ value }}</p>
</li>

Using ng-repeat how do I remove the empty UL from the dom

I'm using a simple ng-repeat to create a filtered input that allows you to filter a list of schools.
I would like the UL to be removed from the DOM when there are no suitable results (i.e. any li's).
Example: DOM
<ul id="filter_quickfind" data-ng-show="query" class="dropdown-menu">
<!-- ngRepeat: school in schools | filter: query -->
</ul>
My Code:
<input id="input_quickfind" ng-model="query" placeholder="Find a school" class="form-control" autofocus>
<ul id="filter_quickfind" data-ng-show="query" class="dropdown-menu">
<li data-ng-repeat="school in schools | filter: query">
{{school.name}}
</li>
</ul>
I've seen a solution on stack overflow that comes close but I couldn't relate it to my code. If anyone can help that would be much appreciated.
Use an ng-if on the length of the schools array:
<ul id="filter_quickfind" data-ng-show="query" class="dropdown-menu" ng-if="schools.length">

Resources