Custom counter inside ng-repeat directive - angularjs

I can not initialize custom counter and reset it inside ng-repeat directive. I have a colors array with three item
$scope.colors=['color1','color2','color3']
My colors array length is 2. I want to bind class in my ng-repeat list colors array 0 to 2 length. When it reach max of it's length then reset it to 0 and again repeat. I can implement it other place like php,jquery etc but i can't implement it on angular view.
<!-- single cat -->
<div ng-repeat="cat in contacts|filter:search.name">
<div class="item item-divider">
{{cat.name}} <span class="badge badge-positive">{{cat.data.length}}</span>
</div>
<!-- cat contact single -->
<a class="item" href="#" ng-repeat="p in cat.data">
<h2 class="letter colors[customerCounterIndex]">{{p.name.charAt(0)}}</h2>
<span class="name">{{p.name}}</span>
<p>{{p.phone}}</p>
</a>
<!-- end cat contact single -->
</div>
<!-- end single cat -->

Try this, <h2 class="letter" ng-class="colors[$index % colors.length]">

Related

Is there a way to generate new span elements for each value we iterate in *ngFor Angular 8?

I want to generate a span element for each saved tag from my collection tag's array.
I use firebase and get in *ngFor loop i get one big span element with all saved tags separated by comma, instead of getting a span for each tag. Is there any way that i can't prevent this from happening. Also i have created an interface for Saved.
Thanks in advance.
<div class="card">
<div class="card-body">
<h5 class="card-title text-center">{{saved?.title}}</h5>
<hr />
<div *ngFor="let tag of saved.tags">
<span class="badge badge-pill badge-primary">{{saved?.tags}}</span>
</div>
<hr /> View
</div>
</div>
//Saved interface in Saved.ts file
export interface Saved {
id: string;
title: string;
tags: string[];
}
Try having your code like this. This should make the span element repeat rather than the div and then make sure to reference the individual tag rather than the array inside.
If the tag has a name / title attribute swap {{ tag }} for {{ tag.title}}
looking at the interface its just {{ tag }}.
<div>
<span *ngFor="let tag of saved.tags" class="badge badge-pill badge-primary">
{{tag}}
</span>
</div>
Reference to Angular docs on using *ngFor to display data.
At the moment, you are referencing the array inside your *ngFor. So, as a result, you should see the whole list of n tags, for n times. If you switch from {{saved?.tags}} to {{tag}}. You will see one div per tag including one span and a single tag inside.
So for getting one span per tag, use it like the following:
<div class="card">
<div class="card-body">
<h5 class="card-title text-center">{{saved?.title}}</h5>
<hr />
<div>
<span class="badge badge-pill badge-primary" *ngFor="let tag of saved.tags">
{{tag}}
</span>
</div>
<hr />
View
</div>
</div>

How to access key value in angular js using ng-repeat?

I am trying to show the value from my json files using ng-repeat in angular js but I am unable to do that.
This is my code which I am trying:
<div ng-repeat = "x in myWelcome.definition">
{{x.attributes[0].children[0].node_id}}
<hr>
</div>
I have tried this and it is working:
<!-- first attributes start -->
<div ng-repeat = "x in myWelcome.definition.attributes">
{{x.rm_attribute_name}}<hr>
<div ng-repeat="a in x.children">
<div ng-if ="a.attributes">
a: {{a.attributes[0].rm_attribute_name}}
<div ng-if= "a.attributes[0].children">
chld
</div>
</div>
</div>
</div>
<!-- second attributes end -->
I am trying to understand how this line is working {{a.attributes[0].rm_attribute_name}} why it is not working like this {{a.attributes1.rm_attribute_name}} this is confusing. How it is shwoing all the results when I am using 0 and index.
And my json file is here in the plunker:
Plunker link of json and code
So how can I iterate here using ng-repeat here this code:
{{myWelcome.definition.attributes[0]}}
is working how can I show this in my view using ng-repeat I need to show all the attributes and child using ng-repeat.
ng-repeat can be used in the following way:
<div ng-repeat = "(key,value) in myWelcome.definition.attributes">
Key:{{key}} and value :{{value}}
<hr>
</div>
OR you can Try this:
<div ng-repeat = "x in myWelcome.definition.attributes">
<div ng-repeat="a in x.children">
a:{{a.node_id}}
</div>
</div>
Edited Plunker
I can see you are trying to implement ng-if and ng-repeat for your json file. You need to understand how ng-repeat works you can always check the index of you array using {{$index}}. So for your kind of problem I think this is the solution you should try.
<!-- first attributes start -->
<div ng-repeat = "x in myWelcome.definition.attributes">
{{x.rm_attribute_name}}<hr>
<div ng-repeat="a in x.children">
{{$index}}
<div ng-if ="a.attributes">
<div ng-repeat="b in a.attributes">
<hr>
{{b.children.length}}
<div ng-if="b.children.length > 1">
If the array is more than 1 please do the magic here
</div>
</div>
<div ng-if= "a.attributes[0].children">
chld
</div>
</div>
</div>
</div>
<!-- second attributes end -->
You can always see the indexes using {{$index}} and you should always use .length to check if it has more than 1 value. This way you can achieve what you want and you should also learn something about arrays in javascript and what is the differnece between dot and bracket. Please read this http://www.dev-archive.net/articles/js-dot-notation/. I think you should learn the basics of javascript.

ng-repeat + ng-switch: how to use correctly?

Premise: I've seen several similar questions. But I can't really figure out how to solve my doubt.
I have an array of objects:
$scope.messages = [obj1, obj2, ...];
where each object has the following structure:
{
id: <int>,
printOnlyFirst: <boolean>,
text1: <string>,
text2: <string>
}
where text1 / text2 are conditionally printed (in real time through track by) according to printOnlyFirst.
<div id="container">
<div ng-switch="printOnlyFirst" ng-repeat="message in messages track by message.id">
<div ng-switch-when="true" class="text1"> <!-- case 1 -->
{{message.text1}
</div>
<div ng-switch-when="false" class="text2"> <!-- case 2 -->
{{message.text2}
</div>
</div>
</div>
I think this code is fine.
However I noticed that
<div ng-switch="printOnlyFirst" ng-repeat="message in messages track by message.id">
is printed for each single element of the ng-repeat loop, together with it's content (either case 1 or 2).
Is this normal?
Is there a better solution to avoid such DOM overhead?
From https://docs.angularjs.org/api/ng/service/$compile#-priority-:
Directives with greater numerical priority are compiled first.
ngSwitch executes at priority 1200 while ngRepeat executes at priority 1000, which isn't the order you need.
You'll have to use a nested component (a div for example):
<div id="container">
<div ng-repeat="message in messages track by message.id">
<div ng-switch="message.printOnlyFirst">
<div ng-switch-when="true" class="text1"> <!-- case 1 -->
{{message.text1}
</div>
<div ng-switch-when="false" class="text2"> <!-- case 2 -->
{{message.text2}
</div>
</div>
</div>
</div>
Don't forget to switch on message.printOnlyFirst rather than printOnlyFirst.

AngularJS + Bootstrap + Filter

I'm trying to filter an user list. I'm using a custom Bootstrap version and want to display a 4 columns table.
So far, I've the following code:
<div ng-repeat="user in users | filter:searchValue | orderBy: 'username'">
<span ng-switch on="$index % 4">
<span ng-switch-when="0">
<div class="row-fluid">
<div class="span3" ng-if="users[$index+0]">
<user-item ng-model="users[$index+0]" on-click="showUser(userId)"></user-item>
</div>
<div class="span3" ng-if="users[$index+1]">
<user-item ng-model="users[$index+1]" on-click="showUser(userId)"></user-item>
</div>
<div class="span3" ng-if="users[$index+2]">
<user-item ng-model="users[$index+2]" on-click="showUser(userId)"></user-item>
</div>
<div class="span3" ng-if="users[$index+3]">
<user-item ng-model="users[$index+3]" on-click="showUser(userId)"></user-item>
</div>
</div>
</span>
</span>
</div>
So far, it works perfectly when there is no filter set.
When I set a searchValue, the $index cannot display the correct value (It will always start from 0 to the lengh of the filtered array).
My question is: Is there a way to correctly display the results in a 4-cols table and to filter the result ?
I don't think you need to add conditions in order to create a 4 column table using bootstrap css, simply use ng-repeat in a col-* element or using your custom span class (which I assume is created using bootstrap's mixins to create rows and columns).
DEMO
HTML
<input ng-model="searchValue.username" />
<div class="row-fluid">
<!-- simply change col-xs-3 to span3 -->
<div class="col-xs-3" ng-repeat="user in users | filter:searchValue | orderBy: 'username'">
{{user.username}}
<user-item ng-model="user" on-click="showUser(user.id)"></user-item>
</div>
</div>
If the markup above does not work in your case because of the custom bootstrap that you're using, then you are probably better off with a filter that partitions your current array into sections of subarrays that represents a row-column relationship, answered by m59 in this SO Answer.
Next time try to give a shot to ngTasty table http://zizzamia.com/ng-tasty/directive/table it's based to bootstrap css table :)

Show only open div with angular if

I'm trying to acheive the same behavior as the spring code below:
<c:forEach items="${data}" var="data" varStatus="contador">
<c:if test="${(contador.count-1)%3==0}">
<div class="conjunto-${conjunto} row"> <!-- Show opening div -->
</c:if>
<!-- Some HTML goes here -->
<c:if test="${((contador.count-1)%3==2)}">
</div>
</c:if>
</c:forEach>
Explaining: I want a new div from class row only after 3 other HTML elements have been added.
I have tried this with ng-if, like this:
<div ng-repeat="data in DATA">
<div class="conjunto-{{$index/3}} row" ng-show="$index % 3 == 0" ng-include="'html.html'">
</div>
<div ng-show="$index % 3 != 0" ng-include="'html.html'">
</div>
</div>
But it obviously doesnt work because only one element with be inside de div.row.
Is there an if-clause with which I could add only the opening div and then close it later?
Thanks in advance.
Ok the best way to do this IMO is 2 fold, in your controller have a method similar to this
$scope.createDataChunks = function() {
var a = $scope.DATA,
retArr = [];
while(a.length) {
retArr.push(a.splice(0,3));
}
return retArr;
}
This would give you an array of arrays, each containing 3 (or less) items in it, you then have this as your markup
<div ng-repeat="data in createDataChunks()">
<div class="conjunto-{{$index/3}} row" ng-show="$index % 3 == 0" ng-include="'html.html'">
<!-- put custom HTML here -->
</div>
</div>
I think that's roughly what you are after?

Resources