AngularJS Loops and Formatting - javascript

very new to AngularJS so please forgive me if this is a stupid question.
I need to output my data in a grid like format (using Ionic) and i need to have a div for a row and separate divs for columns, like this
<div class="row">
<div class="col-33">Item 1</div>
<div class="col-33">Item 2</div>
<div class="col-33">Item 3</div>
</div>
<div class="row">
<div class="col-33">Item 4</div>
<div class="col-33">Item 5</div>
<div class="col-33">Item 6</div>
</div>
My data is within a list, much like this.
$scope.images = [];
$scope.images.push({text: 1});
$scope.images.push({text: 2});
$scope.images.push({text: 3});
$scope.images.push({text: 4});
$scope.images.push({text: 5});
$scope.images.push({text: 6});
How can i use the $scope.images list to output my as a grid?
The closest i have got is below, but it doesnt work.
<ion-content>
<div class="list list-inset" ng-init="myIndex = 0">
{{myIndex }} : {{ images.length }}
<div ng-repeat="myIndex < images.length" >
<div class="row" ng-repeat="colIndex in [0, 1, 2]" ng-init="colIndex = 0">
<div ng-show="myIndex + colIndex < images.length" class="col-33" ng-init="myIndex = myIndex + 1">
{{ myIndex }}:{{ colIndex }}:{{myIndex + colIndex}}:{{ images[myIndex + colIndex].text}}
</div>
</div>
</div>
</div>
</ion-content>
Is there such a thing as a while loop? I was hoping i could increase the $index variable if i used ng-repeat="item in images", but not sure how to do that either.
Thanks in advance

Something like this? fiddle
<span style="float: left">{{item}}</span><br ng-if="($index+1)%3 == 0"/>
I simply break the line every three items, but we could expand on this approach.
Update with complete, working solution: fiddle
<div class="container">
<div ng-repeat="item in items" ng-if="$index%3==0" class="row">
<span ng-if="$index<items.length" style="float: left">{{items[$index]}}</span>
<span ng-if="($index+1)<items.length" style="float: left">{{items[$index+1]}}</span>
<span ng-if="($index+2)<items.length" style="float: left">{{items[$index+2]}}</span>
</div>
</div>
The code is pretty self-explaining: the solution creates a row every three elements, and inserts the elements only if they actually exist.

<div class="row" ng-repeat="photo in photos" ng-if="$index % 3 == 0" ng-init="photoIndex = $index">
<div ng-repeat="i in [0,1,2]" ng-if="(photoIndex + i)<photos.length" class="col-33">
<img ng-src="{{photos[photoIndex+i]}}">
</div>
</div>
Here is a more compact version of the above answer.

Related

Start and close element on condition in AngularJS ng-repeat

I've a HTML structure which looks like this :
<div class="row">
<div class="md-4">1</div>
<div class="md-4">2</div>
<div class="md-4">3</div>
</div>
<div class="row">
<div class="md-4">4</div>
<div class="md-4">5</div>
<div class="md-4">6</div>
</div>
<div class="row">
<div class="md-4">7</div>
<div class="md-4">8</div>
<div class="md-4">9</div>
</div>
and I've JS :
var abc = [1,2,3,4,5,6,7,8,9]
currently as per my structure I can't directly run ng-repeat as after every 3 records I want starts and ends
I want something similar like
<div ng-repeat="val in abc" class="row" ng-if="$index%3==0">
<div>{{val}}</div>
</div>
but above codes don't work and I know its incorrect way but I want something similar to that
please try with this code:
<div ng-repeat="val in abc track by $index" class="row" ng-if="$index%3==0">
<div>{{val}}</div>
</div>
If you've used lodash before
var arr = _.chunk(abc,3);
//makes your array like [[1,2,3],[4,5,6],[7,8,9]]
<div ng-repeat = "a in arr" class = "row">
<div ng-repeat="b in a" class="md-4">{{b}}</div>
</div>
you can lookup lodash here

Ionic + AngularJS: ng-repeat filter not working on grid layout but works in list

I am currently learning building apps with ionic v1 and angular.
Here's the scenario, I'm trying to make a grid of cards and was able to do it by following the tutorial on this link.
I was able to populate the grid with cards using json data. However, I also need to add a search box in order to filter the results. I used angularJS ng-repeat filter on the view but it is not filtering it correctly.
here's my code:
angular.module('starter')
.factory('Disasters', function() {
var disasters= [{
id: 0,
name: 'Earthquake',
face: 'img/earthquake/thumbs.PNG',
}, {
id: 1,
name: 'Flash Floods',
face: 'img/flood/thumbs.png',
}, {
id: 2,
name: 'Typhoon',
face: 'img/typhoon/thumbs.png',
}, {
id: 3,
name: 'Avalanche',
face: 'img/avalanche/thumbs.png',
}];
return {
all: function() {
return disasters;
},
remove: function(disaster) {
disasters.splice(disasters.indexOf(disaster), 1);
},
get: function(disasterID) {
for (var i = 0; i < disasters.length; i++) {
if (disasters[i].id === parseInt(disasterID)) {
return disasters[i];
}
}
return null;
}
};
})
.controller('DisasterCtrl', function($scope,$state,$ionicSideMenuDelegate,Chats,Facts){
$scope.disasters = Disasters.all();
})
and here's the code for my view
<ion-content>
<input type="text" ng-model="search">
<div ng-repeat="disaster in disasters | filter: search" ng-if="$index % 2 === 0">
<div class="row">
<div class="col col-50 no-padding" ng-if="$index < disasters.length">
<div class="list card card-cell">
<div class="item item-image background-image" back-img="{{disasters[$index].slider[0].image}}">
</div>
<div class="item item-avatar" ng-click="href({{disasters[$index].id}})">
<p class="bold uppercase font12">{{disasters[$index].name}}</p>
</div>
</div>
</div>
<div class="col col-50 no-padding" ng-if="$index < disasters.length">
<div class="list card card-cell">
<div class="item item-image background-image" back-img="{{disasters[$index + 1].slider[0].image}}">
</div>
<div class="item item-avatar" ng-click="href({{disasters[$index + 1].id}})">
<p class="bold uppercase font12">{{disasters[$index + 1].name}}</p>
</div>
</div>
</div>
</div>
</div>
</ion-content>
when I type something on the search text box it always shows the first two object in the JSON data.
If I change the view into a list the filter works, however it is required to apply the grid styling on the view.
Thanks!
Pluker link of the code : plnk code link
The problem with your grid layouting is that you are using the ng-repeat in a row instead of the columns so when the search item is among a particular it returns the full row because thats where your item is located. so i created a code to help you sort it in plnk where i used the ng-repeat in a column instead of the row and added a style to the row to make it break which is this
class="row" style="flex-wrap: wrap;"
Input: <input type="text" ng-model="search.name" style="border:1px solid #ccc">
<br>
<div class="row" style="flex-wrap: wrap;" >
<div class="col col-50 no-padding" ng-repeat="disaster in disasters | filter: search" >
{{$index}}
<div class="list card card-cell">
<div class="item item-image background-image" back-img="{{disaster.slider[0].image}}">
</div>
<div class="item item-avatar" ng-click="href({{disaster.id}})">
<p class="bold uppercase font12">{{disaster.name}}</p>
</div>
</div>
</div>
</div>
That should work for you as needed. here is the demo running demo
reference from this answer

get sequence of div from html

I have 9 HTML divs as:
<div id="1">1</div>
<div id="2">2</div>
<div id="3">3</div>
<div id="9">9</div>
Now sequence in HTML is : (id) 1 2 3 4 5 6 7 8 9
These divs can be rearranged to get any order in the DOM.
Say after swapping the DOM is like this:
<div id="8">8</div>
<div id="2">2</div>
<div id="5">5</div>
<div id="1">1</div>
(after swapping/reordering) Now sequence in HTML is : (id) 8 2 5 3 4 7 9 6 1
I want to get the order(8 2 5 3 4 7 9 6 1) of div in a span.
<div id="show">Now the sequence is <span id="seq"> </span></div>
Use a common class to get all the div that you need. Then use each to get it's text(or id) and form a string and append it to the dom
HTML
<div id="8" class="sqDiv">8</div>
<div id="2" class="sqDiv">2</div>
<div id="5" class="sqDiv">5</div>
<div id="1" class="sqDiv">1</div>
<span id="sqDom"></span>
JS
var _sq="";
var getDivs = $(".sqDiv");
getDivs.each(function(item,index){
_sq+=$(this).text().trim()+' ';
})
$("#sqDom").text(_sq);
JSFIDDLE
Use map() method and do something like
$('#seq').text(
$('#parent div') // get the swapped divs
.map(function() { // iterate over them to generate an array
return this.id // return id for array element
}).get() // get result as an array
.join(' ') // join the array element
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">
<div id="8">8</div>
<div id="2">2</div>
<div id="5">5</div>
<div id="1">1</div>
</div>
<div id="show">Now the sequence is <span id="seq"> </span>
</div>
This is how I did it:
$("ul div").each(function(){
$("#seq").text($("#seq").text() + $(this).attr("id") + " ");
});
Here is the JSFiddle demo
Hi try this https://plnkr.co/edit/FxemUZMAmEqo2oXvvMXN?p=preview
JS
var IDs2 = [];
$("#swapping").find("div").each(function(){ IDs2.push(this.id); });
$("#seq2").html(IDs2)
HTML
<div id="swapping">
<div id="8">8</div>
<div id="2">2</div>
<div id="5">5</div>
<div id="4">4</div>
<div id="3">3</div>
<div id="2">2</div>
<div id="1">1</div>
</div>
<div id="show2">Now the sequence is <span id="seq2"> </span></div>
I did that using $.each loop,
HTML CODE
<div id="8">8</div>
<div id="2">2</div>
<div id="5">5</div>
<div id="1">1</div>
<div id="show">Now the sequence is <span id="seq"> </span></div>
Jquery
var divs=[];var seq=[];
divs=$("div");
$.each(divs,function(k,v){
if($(v).attr('id')!='show')
{
seq[k]=$(v).attr('id');
}
})
$('#seq').text(seq);
Jsfiddle Example

Bootstrap different col-* with ng-repeat

I've got a movie reviews example application built in angular + bootstrap, I'm trying to build a "grid" of 3 images for medium and up screens, the problem is that when I want to have only 2 images per row for xs screens.
I'm using ng-repeat and populating the imgs inside the cols.
is there a nice way to do this? (I'm aware that the $index + N may be out of bounds, and that there is code duplication here. just want to find a good solution for rearranging the bootstrap grid for different screen sizes on dynamic data)
<div ng-repeat="movie in movies" ng-if="$index % 3 == 0" class="row slide-left">
<div class="col-md-4">
<img ng-src='http://image.tmdb.org/t/p/w185/{{movies[$index].poster_path}}' ng-click="chooseMovie(movies[$index])">
</div>
<div class="col-md-4">
<img ng-src="http://image.tmdb.org/t/p/w185/{{movies[$index + 1].poster_path}}" ng-click="chooseMovie(movies[$index + 1])">
</div>
<div class="col-md-4">
<img ng-src="http://image.tmdb.org/t/p/w185/{{movies[$index + 2].poster_path}}" ng-click="chooseMovie(movies[$index + 2])">
</div>
</div>
<div ng-repeat="movie in movies" >
<div class="col-md-4 col-xs-6">
<img ng-src='http://image.tmdb.org/t/p/w185/{{movie.poster_path}}' ng-click="chooseMovie(movie)">
</div>
</div>
This should do the trick.
I removed the row but i think even with it will works unless you use the clearfix class.
The grid will automatically go on the next line after "12" columns.
So a size of 4 for medium screen means 3 per line, 6 for xs screen ->2/line :)
You can detect bootstrap columns by using the following function:
function findBootstrapEnvironment() {
var envs = ["ExtraSmall", "Small", "Medium", "Large"];
var envValues = ["xs", "sm", "md", "lg"];
var $el = $('<div>');
$el.appendTo($('body'));
for (var i = envValues.length - 1; i >= 0; i--) {
var envVal = envValues[i];
$el.addClass('hidden-'+envVal);
if ($el.is(':hidden')) {
$el.remove();
return envs[i]
}
};
}
The setting a value to the scope based on the return
if(findBootstrapEnvironment()==="Medium"|(findBootstrapEnvironment()==="Large"|){
$scope.size="Medium"
}else{
$scope.size="Small"
}
And then with ng-if you can manage the div to be with 3 or 2 photos like this
Three photos if medium
<div ng-repeat="movie in movies" ng-if="size==medium" class="row slide-left">
<div class="col-md-4">
<img ng-src='http://image.tmdb.org/t/p/w185/{{movies[$index].poster_path}}' ng-click="chooseMovie(movies[$index])">
</div>
<div class="col-md-4">
<img ng-src="http://image.tmdb.org/t/p/w185/{{movies[$index + 1].poster_path}}" ng-click="chooseMovie(movies[$index + 1])">
</div>
<div class="col-md-4">
<img ng-src="http://image.tmdb.org/t/p/w185/{{movies[$index + 2].poster_path}}" ng-click="chooseMovie(movies[$index + 2])">
</div>
</div>
Two photos if small
<div ng-repeat="movie in movies" ng-if="size==small" class="row slide-left">
<div class="col-sm-4">
<img ng-src='http://image.tmdb.org/t/p/w185/{{movies[$index].poster_path}}' ng-click="chooseMovie(movies[$index])">
</div>
<div class="col-sm-4">
<img ng-src="http://image.tmdb.org/t/p/w185/{{movies[$index + 1].poster_path}}" ng-click="chooseMovie(movies[$index + 1])">
</div>
</div>

AngularJs ng-repeat does not update after filter object gets updated

Hi I am working on requirement where my filter object is keep getting changed and because of that i have to change ng-repeat on div.
html code :
<div class="col-md-6" ng-repeat="model in models | filter:{ModelText : '!All models', ModelId: '!FilteredModelIds'}:true">
<div class="well">
<div class="media">
<div class="media-object small"><i class="pp-car"></i></div>
<div class="media-body">
<div class="text-box">
<h3>{{model.ModelText}}</h3><span class="hr-small"></span>
</div>
<div class="dashboard-control clearfix">
<div class="simple-metric text-left sub-metric">
<div class="metric-title">Satisfaction score</div>
<div class="metric-number text-red">{{model.SatisfactionAvg}}</div>
</div>
<div class="simple-metric text-left sub-metric">
<div class="metric-title">Total interviews</div>
<div class="metric-number">{{model.TotalInterviews}}</div>
</div>
</div>
<ul class="list-standard">
<li> View interviews</li>
</ul>
</div>
</div>
</div>
</div>
here is the angular js code:
function getModelId() {
dataFactory.getModelIdByFilter($scope.region, $scope.subregion).success($scope.handleSuccess).then(function (result) {
$scope.FilteredModelIds = result.data;
});
}
Model json :
[{"ModelId":0,"ModelText":"All models","Sequence":0,"TotalInterviews":0,"SatisfactionAvg":0.000000},{"ModelId":1,"ModelText":"A3","Sequence":20,"TotalInterviews":2062,"SatisfactionAvg":9.637245},{"ModelId":2,"ModelText":"A4","Sequence":30,"TotalInterviews":3106,"SatisfactionAvg":9.743721},{"ModelId":3,"ModelText":"A5","Sequence":40,"TotalInterviews":1863,"SatisfactionAvg":9.694041},{"ModelId":4,"ModelText":"A6","Sequence":50,"TotalInterviews":280,"SatisfactionAvg":9.642857},{"ModelId":5,"ModelText":"A8","Sequence":70,"TotalInterviews":46,"SatisfactionAvg":11.217391},{"ModelId":9,"ModelText":"Q5","Sequence":110,"TotalInterviews":3176,"SatisfactionAvg":9.503778},{"ModelId":10,"ModelText":"Q7","Sequence":120,"TotalInterviews":1355,"SatisfactionAvg":9.685608},{"ModelId":11,"ModelText":"R8","Sequence":130,"TotalInterviews":31,"SatisfactionAvg":10.064516},{"ModelId":12,"ModelText":"TT","Sequence":140,"TotalInterviews":408,"SatisfactionAvg":9.764705},{"ModelId":13,"ModelText":"A1","Sequence":10,"TotalInterviews":1087,"SatisfactionAvg":10.097516},{"ModelId":14,"ModelText":"A7","Sequence":60,"TotalInterviews":263,"SatisfactionAvg":10.190114},{"ModelId":15,"ModelText":"Q3","Sequence":105,"TotalInterviews":1045,"SatisfactionAvg":9.542583}]
on page load its showing proper data with filter. but on change of filtered object in my case FilteredModelIds, its not getting updated. any help is appreciated.
please let me know if i am worng here.
Thanks.

Categories

Resources