Using ng-if on a parent ng-repeat - angularjs

I'm starting at front-end development and there´s something that I don't know if it's possible to do using AngularJS and ng-repeat.
I have an array with 3 levels of data so the first ng-repeat lists the level 1, inside it there's another ng-repeat that lists the level 2 anda at last another one that lists level 3. Something like this:
<div ng-repeat="item-1 in level-1">
<div ng-repeat="item-2 in level-2">
<div ng-repeat="item-3 in level-3">
{{item-3.name}} : {{item-3.valid}}
</div>
</div>
</div>
What I wan't to know if it´s possible to use the ng-if directive on the first level repeat but with a condition of the tird level repeat, something like this:
<div ng-repeat="item-1 in level-1" ng-if="item-3.valid == true">
<div ng-repeat="item-2 in level-2">
<div ng-repeat="item-3 in level-3">
{{item-3.name}} : {{item-3.valid}}
</div>
</div>
</div>
Thank you!

What about moving this logic to the controller managing this HTML. For example something like:
$scope.toBeDisplayedItems = [..];
$scope.level1 = [..];
$scope.level2 = [..];
$scope.level3 = [..];
for (var item1 in $scope.level1) {
for (var item2 in $scope.level2) {
for (var item3 in $scope.level3) {
// do something with $scope.level1[item1] $scope.level2[item2] $scope.level3[item3]
// then fill the candidate array to be used in the HTML
$scope.toBeDisplayedItems.push(....);
}
}
}
In your HTML:
<div ng-repeat="item in toBeDisplayedItems">
{{item.name}} : {{item.valid}}
</div>
By the way I didn't get your check on item-3 in top level of first loop, is that actually working?
Anyway I answered you on the way it's done and not on the how.

Related

How to create an independent indexer with default value inside ngRepeat loop

I have a list of posts with comments. I need to traverse through array of comments inside each of the posts on my page. I'm trying to create variable inside ngRepeat for posts which I can use like an indexer to display exact comment for each post. Due to ngRepeat creating nested scope, this variable must be unique for each iteration. But when I'm trying to change it with ng-click, it doesn't change.
My ngRepeat:
<div class="question_block col-xs-12"
ng-repeat="answer in question.content.answer track by answer.id">
is followed by <span style="display:none">{{counter=0}}</span>. And then I'm showing some items like <span>{{answer.comments[counter].user.organization.title}}</span>. When I'm trying to do something like <a href ng-click="counter++">Increment</a> nothing happens. What's the matter ?
Use ng-init="counter = 0" and attach your ng-click to a function in your controller:
<div ng-repeat="item in items track by $index" ng-init="counter=0">
{{item}} ({{counter}})
<button ng-click="clickHandler()">Increment</button>
<hr />
</div>
Then, to increment counter in the context of the event, use this.counter
$scope.clickHandler = function() {
this.counter++;
};
Plunker demo : http://plnkr.co/edit/J4d0JlJSKD7i4OfMT2r4?p=preview

Angularjs ng-repeat iterate by 2

I have a for loop in my MVC application like this
for(var i = 0; i < data.length; i +=2){
<div class='#(i== 0? "item active": "item")'>
<div>
#Html.Raw(data[i].Description)
</div>
<div>
#Html.Raw(data[i + 1].Description)
</div>
</div>
}
I want to convert the above code in angularjs.
Means every loop render the record from current and next array index, say i = 0 then render first and second record detail.
Actually it is big object, for clarity I reduce the code, I want to write the same code in ng-repeat
See the fiddle
I end up with a dirty trick:
<div ng-repeat="item in data"
ng-class="{active: $first}" class="item row"
ng-if='$index % 2 == 0'>
<div class='col-lg-6'>{{ item.a }}</div>
<div class='col-lg-6'>{{ data[$index + 1].a }}</div>
</div>
If $index % 2 == 0 only then render, means 0, 2, 4 .. it work as I want.
See to codepen.
You essentially want something like this:
<div ng-repeat="dataEntry in data" ng-class="{active: $first}" class="item">
<div>{{ dataEntry.Description }}</div>
<div ng-if="!$last">{{ data[$index + 1].Description }}</div>
</div>
Use ng-repeat to loop over your data entries
Use ng-class to only apply 'active' class to the first entry (you have access to $first, $last, $even, and $odd, (which are booleans) inside of an ng-repeat scope)
dataEntry represents each entry for each iteration of your data. Use {{ }} to access and render it's contents
You can use $index + 1 to grab the next entry in the array of entries.
I would assume you know that data in this scenario has to be attached / accessible from your $scope.

Angularjs ng-repeat dynamic property

<div (ng-repeat='item in items') >
{{item.name}} //works
{{item["name"]}} // works
</div>
how do i repeat item[property] dynamically without using ".name" or ['name']?
To dynamically go through properties, you're going to need to call Object.keys(item) and then iterate through them. It's best to prune your data from within your controller, to minimize the finagling you'll need to do within your HTML.
If you do want to try to do this within your HTML-Angular structures, you could define:
$scope.returnAllKeyValues = function(obj){
var x = Object.keys(obj),
arr = [];
for(var i = 0; i<x.length; i++){
arr.push(obj[x[i]]);
}
return arr;
}
What this function does is it takes in your JSON object, then parses through it and collects all the values for every key within it.
Then, within your HTML, you can write something like this:
<h3>FIFA Mactch Summary:</h3>
<div ng-app ng-controller="MyCtrl">
<ul>
<li ng-repeat="item in items">
<span ng-init="keyValues = returnAllKeyValues(item)">
<span ng-repeat="keyValue in keyValues">{{key}} </span>
</span>
</li>
</ul>
</div>
Here you see, within your original ngRepeat, we initialized the array keyValues with all the values from item's keys via the function defined above. Then, ng-repeat through that, and you have everything printed without knowing what they are.
Here is a Fiddle with it working:
http://jsfiddle.net/RkykR/2771/
This was what i was looking for....Thanks
https://www.codementor.io/debugging/4948713248/request-want-to-use-values-in-nested-ng-repeat

How to bind array with ng-bind-html directive in angularJS?

I want to show for every item different description.
This is the controller:
todoApp.controller('todos',function($scope,todoFactory){
todoFactory.getTodos().success(function (data) {
courses = x2js.xml_str2json(data);
$scope.todos = courses.rss.channel.item;
for(var i = 0 ; i < $scope.todos.length ; i++){
item = $scope.todos[i];
console.log(item.description);
$scope.message = item.description;
}
});
this is the html:
<div ng-controller="todos" class="list" style="padding-top: 8%">
<div class="list card" ng-repeat="todo in todos | filter:search" >
<div class="item item-avatar" ng-click="openLink(todo.link)" >
<img src="Bla-Bla-Logo-1.png">
<h2>{{todo.title}}</h2>
<p>{{todo.pubDate | limitTo:25 }}</p>
</div>
<div class="item item-body">
<p ng-bind-html="message"></p>
<p>
1 Like
5 Comments
</p>
</div>
</div>
<!--end list card-->
</div>
<!--end todos-->
Just to explain the code I get xml and convert into json so todos is array of objects.
Message is entering every object and get the description (but in the description has tags so i use ng-bind-html directive to show it properly).
I understand that $scope.message will hold just the last description. How to make it to belong in the ng-repeat so I can get different description for different item?
Thanks.
replace
<p ng-bind-html="message"></p>
with
<p ng-bind-html="todo.description"></p>
please provide the data which is you want to displayed repeatedly.
How data is represented.You are getting last one because it is overriding.
The "ngBind" attribute tells Angular to replace the text content of the specified HTML element with the value of a given expression, and to update the text content when the value of that expression changes.
Typically, you don't use "ngBind" directly, but instead you use the double curly markup like {{ expression }} which is similar but less verbose.

angularjs how set right scope for function?

have this ng-repeat
<li class="tmmenu-admin-tabs-builder-panel-portlet" ng-repeat="question in questions">
<div>
<span class="tmmenu-admin-tabs-builder-panel-portlet-toggler" ng-click="tatbppTogler()">{{{tatbppt}}}</span>
<span class="tmmenu-admin-tabs-builder-panel-portlet-number">{{question.id}}</span>
{{question.text}}
</div>
<div class="tmmenu-admin-tabs-builder-panel-portlet-options" ng-show="showTatbppo">
...
</div>
</li>
I want, for click in "tmmenu-admin-tabs-builder-panel-portlet-toggler" change visibility "tmmenu-admin-tabs-builder-panel-portlet-options" and change text in "tmmenu-admin-tabs-builder-panel-portlet-toggler".
And i write this code for get result:
$scope.tatbppTogler = function(){
$scope.showTatbppo = !$scope.showTatbppo;
if($scope.showTatbppo){
$scope.tatbppt = "-";
}else{
$scope.tatbppt = "+";
}
}
It's works, but changed dom in all "Li", how changed only current (where user click) "li"?
You can do it like this:
<li class=portlet" ng-repeat="question in questions">
<div>
<span class="toggler" ng-click="showTatbppo=!showTatbppo">{{showTatbppo ? "+" : "-" }}</span>
<span class="number">{{question.id}}</span>
{{question.text}}
</div>
<div class="options" ng-show="showTatbppo">
...
</div>
</li>
Working fiddle, with this concept:
http://jsfiddle.net/x1nguaxj/
btw. You have very-very-very long css class names :)
1 way
you can pass this in ng-click="tatbppTogler(this)" and then in function manipulate with this
2 way
you can create custom directive and apply it to your li element and then on this directive bind click to element and listen , and on click function will be triggered your listener and you will have access on this element
You can create an attribute id for each question and then change based on the id of the question you clicked
I would suggest you'd take a look at $index. From the angularjs docs:
iterator offset of the repeated element (0..length-1)
Using this, you can clearly determine the certain div that was clicked on.

Resources