Trouble with ng-repeat angular js - javascript

I have an angular ng-repeat like bellow,
<div class="row" >
<div class="col-md-6" ng-repeat="(index,data) in mydata">
<-- my content -->
</div>
</div>
This will create output like below,
<div class="row" >
<div class="col-md-6" ng-repeat="(index,data) in mydata">
<-- my content -->
</div>
<div class="col-md-6" ng-repeat="(index,data) in mydata">
<-- my content -->
</div>
<div class="col-md-6" ng-repeat="(index,data) in mydata">
<-- my content -->
</div>
-----------------------
----------------- Etc.
</div>
But i need to repeat <div class="row" > also which contain two <div class="col-md-6" in each row.
This output needs like
<div class="row" >
<div class="col-md-6" ng-repeat="(index,data) in mydata">
<-- my content -->
</div>
<div class="col-md-6" ng-repeat="(index,data) in mydata">
<-- my content -->
</div>
</div>
<div class="row" >
<div class="col-md-6" ng-repeat="(index,data) in mydata">
<-- my content -->
</div>
<div class="col-md-6" ng-repeat="(index,data) in mydata">
<-- my content -->
</div>
</div>
<div class="row" >
<div class="col-md-6" ng-repeat="(index,data) in mydata">
<-- my content -->
</div>
<div class="col-md-6" ng-repeat="(index,data) in mydata">
<-- my content -->
</div>
</div>
------- Etc
Is it possible to do with this usingng-repeat?

As mentioned in comment, if you want your row to repeat with each element in mydata, you would need to put ng-repeat on the <div> that contains row.
Its upto you to decide if you want to hardcode the inner <div> like this:
<div class="row" ng-repeat="data in mydata">
<div class="col-xs-6"> {{data.index}} </div>
<div class="col-xs-6"> {{data.value}} </div>
</div>
or use another ng-repeat on it.
<div class="row" ng-repeat="(index,data) in mydata">
<div class="col-xs-6" ng-repeat="i in data"> {{i}} </div>
</div>
Where mydata is an array of json with following structure:
$scope.mydata = [{index:0,value:'hello'},
{index:1,value:'hello1'},
{index:2,value:'hello2'}
]
here's the plunkr
UPDATE:
If you have data like following,
$scope.mydata = [{value:'hello0'},
{value:'hello1'},
{value:'hello2'},
{value:'hello3'}];
and you want to display it like
hello0 hello1
hello2 hello3
in the view, then you would need to make a check for elements occurring at even iterations and print elements at $index and $index+1. I used $even for the same. but you can also create a custom filter.
<div class="row" ng-repeat="data in mydata">
<div ng-if="$even">
<div class="col-xs-6" > {{mydata[$index].value}} </div>
<div class="col-xs-6" > {{mydata[$index + 1].value}} </div>
</div>
</div>
Heres the updated plunker

Create a directive:
angular.module(....)
.directive('myRows',function(){
return {
restrict : 'A',
template : '<div class="row"><div class="col-md-6" ng-repeat="(index,data) in mydata"><-- my content --></div></div>'
};
});
assumption here is that mydata is defined on the scope of the surrounding controller.
Use it in your html:
<div data-my-rows><div>

Yes ng-repeat is possible to do that.
Here is example code from my project
<tbody>
<tr ng-repeat="proj in projects>
<td>
{{proj.projectID}}
</td>
<td>
{{proj.projectName}}
</td>
<td>
{{proj.project.start date | date:'mediumDate'}}
</td>
<td>
{{proj.projectStatus}}
</td>
</tr>
</tbody>
I hope this would help

So, you now have two answers that correctly address your question and will produce the results you requested, but I wanted to give you some advice (albeit unsolicited) about your Bootstrap structure.
In Bootstrap, it is perfectly acceptable to not repeat your rows for every 12 grid units. In fact, if you want to use multiple responsive column classes together, such as using col-lg-4 and col-md-6 to produce 3 columns on large viewports and 2 on medium viewports, you cannot insert rows between your repeated content.
Since col classes use float and percentages, you don't have to worry about "terminating" the row. Elements will simply float next to one another up to 12 grid units and then start a new natural horizontal "row." That is how Bootstrap's responsive grid works.
You should use rows for two purposes:
To nest columns inside of columns. See my answer here for a
visual explanation of this topic. or
To create horizontal groups of columns. This has the purpose of grouping elements together and clearing column floats for subsequent columns.
What I'm saying is that your initial ng-repeat structure was better and will provide you with a more flexible outcome.

Related

ngFor and ngIf on bootstrap columns

I want to hide and show bootstrap columns inside a row based on search value.
Here is a simple template:
<div class="container py-5">
<p class="text-center"><input type="text" placeholder="search" [(ngModel)]="searchVal"></p>
<div class="row">
<div *ngFor="let val of values" class="col-4 my-2">
<ng-container *ngIf="val.toLowerCase().indexOf(searchVal.toLowerCase())!=-1">
{{val}}
</ng-container>
</div>
</div>
</div>
And the component:
export class AppComponent {
searchVal : string = "";
values = ['Manager', 'Model', 'Teacher', 'Student'];
}
The ideal solution is to use ngFor and ngIf on column:
<div class="row">
<div *ngFor="let val of values" class="col-4 my-2" *ngIf="val.toLowerCase().indexOf(searchVal.toLowerCase())!=-1">
{{val}}
</div>
</div>
But we all know that its not possible to use both on same element.
In the code I provide here, I used ng-container to solve this issue, however, since the ng-container is not inside the column, if a value does not match, the column remains displayed and its content is hidden which looks ugly. Try to write the letter "t" in the search field to see what I mean. The solution that I am looking for is to remove the entire column if its value does not match.
Here is a running code: https://angular-rgc8f7.stackblitz.io
Swap your div and ng-container:
ng-container has the for loop and div has the if condition
<div class="container py-5">
<p class="text-center"><input type="text" placeholder="search" [(ngModel)]="searchVal"></p>
<div class="row">
<ng-container *ngFor="let val of values">
<div *ngIf="val.toLowerCase().indexOf(searchVal.toLowerCase())!=-1" class="col-4 my-2">
{{val}}
</div>
</ng-container>
</div>
</div>
Try the following code.
<ng-container *ngFor="let val of values">
<div class="col-4 my-2"
*ngIf="val.toLowerCase().indexOf(searchVal.toLowerCase())!=-1">
{{val }}
</div>
</ng-container>
Couldn't you just add a function in your component to dynamically filter the values before iteration. e.g
<div class="container py-5">
<p class="text-center"><input type="text" placeholder="search" [(ngModel)]="searchVal"></p>
<div class="row">
<div *ngFor="let val of filterValues(values, searchVal)" class="col-4 my-2">
{{val}}
</div>
</div>
</div>
In your component;
filterValues(values: string[], searchVal: string) {
return values.filter((val: string) => {
return val.toLowerCase().indexOf(searchVal.toLowerCase())!=-1;
});
}
Change detection on your search value will cause a refilter, filtering on the current search value, and value list, and updating your table.
This way, you don't need the ng-container at all, and, if you ever need to filter based on other criteria too, you can do it all in one place :)
StackBlitz Example: https://stackblitz.com/edit/angular-miow53

display json data from array

I'm trying to display some json data I got from a get request. So far I've been able to display other arrays with no problem, but I'm having trouble displaying this particular array for some reason, and I'm not getting any errors.
the one that won't display correctly is the showtimes array.
<div *ngIf="show">
<div *ngFor="let shows of show"class="showtime">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{{shows.title}}</h3>
</div>
<div class="panel-body" >
<div class="row">
<div class="col-md-7 col-sm-5 col-xs-12 ">
<img class="thumbnail movie_pic" src="http://developer.tmsimg.com/{{shows.preferredImage.uri}}?api_key={{api}}"><br>
</div>
<div class="col-md-5 col-sm-7 col-xs-12">
<ul class="list-group">
<li class="list-group-item">Genres: {{shows.genres}}</li>
<li class="list-group-rel">Release Date: {{shows.releaseDate}}</li>
<li class="list-group-rel">{{shows.longDescription}}</li>
<li *ngFor="let shows of show.showtimes" class="list-group-rel">shows.theatre.name</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
You are missing {{}} expression
<li *ngFor="let shows of show.showtimes" class="list-group-rel">{{shows.theatre.name}}</li>
EDIT
Change it to some other variable name, since you are already using shows,
<li *ngFor="let showdetail of show.showtimes" class="list-group-rel">{{showdetail.theatre.name}}</li>
As it looks from your snapshot, the array of objects is stored in variable showtimes, if that is the case, try the below code:
<li *ngFor="let detail of showtimes" class="list-group-rel">
{{detail.theatre.name}}
</li>
A nested ngFor loop solved the problem..
<div *ngFor="let shows of show">
<div *ngFor="let detail of shows.showtimes">
<p>{{detail.theatre.name}}</p>
</div>
</div>
works perfectly, thanks for the help

Bootstrap two column layout and ng-repeat (angularjs)

I'm trying to create a two col layout with ng-repeat.
<div class="row">
<div class="col-md-6" ng-repeat="item in items">
Item: {{item}}
</div>
</div>
This results in the following problem:
P.S. This problem has been answered before with native CSS cols but I want to do it with bootstrap.
P.S. The solution proposed below is not working.. anyone got any other ideas please?
You'll have to break it into two seperate columns, but it should be pretty easy after that:
<div class="row">
<div class="col-md-6" ng-repeat="item in items | limitTo: items.length /2: 0">
Item: {{item}}
</div>
<div class="col-md-6" ng-repeat="item in items | limitTo: items.length /2: items.length /2">
Item: {{item}}
</div>
</div>
for that i'm taken two tables
keep bootstrap styles
<table> <tr ng-repeat="cl in codelist" ng-if="$index<codelist.length/2">
<td>{{$index}}</td>
</tr></table>
<table> <tr ng-repeat="cl in codelist" ng-if="$index>=codelist.length/2">
<td>{{$index}}</td>
</tr></table>
that it show order by ordey
1 3
2 4
5 6
like this

AngularJS - Showing different divs based on the ng-if result

I've got a simple chat app in AngularJS, and I'm sending a message to the view which is being outputted on the front end like this:
<div id="messages" class="col-xs-12 chat-messages">
<div class="col-xs-12 chat-message" ng-repeat="message in chatMessages">
<div class="you">
<ul class="media-list">
<li class="media">
<div class="media-left">
<div class="media-object img-circle" style="background-image: url( {{message.avatar_url}} )"></div>
</div>
<div class="media-body">
<div class="media-heading text-muted small">
{{message.nickname}}
</div>
<div class="message-content bubble">
{{message.content}}
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
At the moment I am just going through the chatMessages array and outputting them using this div. I have given each message another attribute of kind where I will send to the view different kinds of messages, such as userMe, userOther, global etc. and I will need to use a slightly different HTML markup for each kind of message. I understand that this should be done using ng-if in AngularJS, but I don't quite know how to go about this.
From the view, I will need to output some different HTML depending on the message.kind value.
Any ideas?
If you have several possible div options for each element, I'd use ng-switch, like Tom said in the comments.
The idea is that you switch on the message.kind, or whatever you want to switch on, and have each div as a "Case" for that:
It would look something like this:
<div class="media-body" ng-switch="message.kind">
<div class="media-heading text-muted small" ng-switch-when="1">
{{message.nickname}}
</div>
<div class="message-content" ng-switch-when="2">
{{message.content}}
</div>
<div class="message-content bubble" ng-switch-default>
default text
</div>
</div>
Fiddle
You have two solution to archieve what you want :
<div ng-repeat="msg in messages">
<div ng-if="msg.kind === 'userMe'">userMeMessage</div>
<div ng-if="msg.kind === 'global'">globalMessage</div>
...
</div>
Or this :
<div ng-repeat="msg in messages|filter:{kind:'userMe'}">
UserMe
</div>
<div ng-repeat="msg in messages|filter:{kind:'global'}">
Global
</div>

Possible to ng-show part of a line?

Basically as the title says I was wondering if it is possible or if someone could come up with an alternative to this. I have this div:
<div id="wrapper">
<div style="margin: 1em">
<h4>User Card for {{username.slice(5)}}</h4>
<div id="canvas-holder" class="col-lg-4">
<canvas id="chart-area" width="20%" height="20%"></canvas>
</div>
<div class="col-lg-8">
Total Score: {{totalscore.toFixed(3)}}
</div>
</div>
</div>
In the line where it says User Card for {{username.slice(5)}} obviously nothing shows up in the {{ }} until there is data for it, but on my page the User Card for part still shows up. I was wondering the possibility of getting only the User Card part to show up while there is no {{username.slice(5)}} and once there is data for that field then the for will show up? Any ideas?
You should be able to wrap a span around the portion you want to show, such as:
<h4>User Card <span ng-show="username">for {{username.slice(5)}}</span></h4>
Try using ng-if on the parent element
<div id="wrapper">
<div style="margin: 1em">
<h4 ng-if="username.slice(5)">User Card for {{username.slice(5)}}</h4>
<div id="canvas-holder" class="col-lg-4">
<canvas id="chart-area" width="20%" height="20%"></canvas>
</div>
<div class="col-lg-8">
Total Score: {{totalscore.toFixed(3)}}
</div>
</div>
</div>

Categories

Resources