Bootstrap different col-* with ng-repeat - javascript

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>

Related

removing and adding a class based on position within an array Angular

I am creating a blog page using angular 5 where each of the blog posts have the class:
col-md-4
However, what I want is the latest blog post (i.e the first on the page) to have the class of :col-md-12.
The html that I have is as follows:
<div *ngFor="let blog of blogs" class="blog-posts col-md-4">
<div class="card">
<img class="blog-img" (click)="goToBlogDetailsPage(blog.sys.id)"src="{{blog.fields.blogimage.fields.file.url}}" class="rounded" alt="">
<div class="info">
<h3 class="author">{{blog.fields.authorInfo}}</h3>
<h2 (click)="goToBlogDetailsPage(blog.sys.id)" class="title">{{blog.fields.title}}</h2>
<p class="short-desc" > {{blog.fields.desciption}}</p>
<img (click)="goToBlogDetailsPage(blog.sys.id)" class="sml-logo" src="/assets/img/logos/logo_blue.png" alt="">
<!-- <button (click)="goToBlogDetailsPage(blog.sys.id)"class="btn btn-info">Open Blog Post</button> -->
</div>
</div>
</div>
</div>
</div>
I have tried accessing the index of the array[0] however I can not seem to alter the styling on just the first item, any suggestions?
Use index and ternary operator to set the class
<div *ngFor="let blog of blogs; let ind = index" class="blog-posts"
[ngClass]="ind === 0 ? 'col-md-12' : 'col-md-4'" >

Attach and Remove a CSS class using ngClass in Angular JS

I am building an app using Angular JS. I am using ng-repeat to loop over list of items. My code is something like below,
<div class="names" ng-repeat="room in rooms" ng-click="getMessages(room.id); active = true; " ng-class="{'blue_act': active}">
<div class="con_cir col-lg-2 col-md-2 col-sm-2">
<div class="grey_cir">
<div class="wht_cir">
<div class="circle1">
<div class="cir_txt">{{room.title | nameInitials}}</div>
</div>
</div>
</div>
</div>
<div class="em_info col-lg-10 col-md-10 col-sm-10">
<div class="em_pr">
<div class="name boldfnt col-lg-7 col-md-7 col-sm-7" ng-class="{'normal-font': active}">
{{room.title}}
</div>
<div class="date col-lg-5 col-md-5 col-sm-5">
{{room.lastActivity | date: 'd/M/yyyy'}}
</div>
</div>
<div class="subject boldfnt col-lg-12 col-md-12 col-sm-12">
Here is your copy of your coupans.
</div>
</div>
</div>
Now I want to apply the class blue_act only when the particular row is selected. I don't want to write any function in the controller to achieve this.
For example When I click the Demo#16 only that row will have the blue background. And when I click the e2Spark only that row will be highlighted using the blue color. Is it possible with only ng-click and ng-class?
Screenshot
Create a new property on controller's scope, called 'selectedRow', and assign room name to it on click.
plnkr
var app = angular.module('plunker', []);
app.controller('MainCtrl', function() {
this.rooms = [
{name: 'room1'},
{name: 'room2'},
{name: 'room3'},
];
this.selectedRow = this.rooms[0].name;
});
.blue_act {
background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<body ng-app="plunker" ng-controller="MainCtrl as main">
selected row: {{main.selectedRow}}
<div class="names" ng-repeat="room in main.rooms" ng-click="main.selectedRow = room.name" ng-class="{'blue_act': main.selectedRow == room.name}">
<div class="con_cir col-lg-2 col-md-2 col-sm-2">
<div class="grey_cir">
<div class="wht_cir">
<div class="circle1">
<div class="cir_txt">{{room.name }}</div>
</div>
</div>
</div>
</div>
</div>
</body>
Replace your click event with this ng-click="getMessages(room.id); reset(); room.active = true; "
and do same for ng-class where you are using as like ng-class="{'normal-font': room.active}"
Add below reset function in your code if you want select at a time single row.
$scope.reset= function(){
angular.forEach($scope.rooms, function(room) {
room.active=false;
});
}
in your ng-click
ng-click="getMessages(room.id); room.active = !room.active;"
in your ng-class
ng-class="{'normal-font': room.active }"
With no controller function you could use
<div class="names" ng-repeat="room in rooms" ng-click="getMessages(room.id);room.active=!room.active;" ng-class="{'blue_act': room.active}">
...
</div>
Or if you just wanted to have one active at the same time this should work:
<div class="names" ng-repeat="room in rooms" ng-click="getMessages(room.id);selectedRoom=room.id;" ng-class="{'blue_act': selectedRoom===room.id}">
...
</div>

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

Javascript in html tags to avoid repetition

I am a newbie to JavaScript and I need to use it with bootstrap for my own web page. My question is now how can I make a loop so that pictures names (stored as an array) can emerge in the right places of the HTML code so I do not have to copy the blocks of code for each picture.
For example :
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive" src="01.jpg">
</div>
</div>
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive" src="01.jpg">
</div>
</div>
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive" src="02.jpg">
</div>
</div>
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive" src="03.jpg">
</div>
</div>
As we can see here the only different text is the src.How can I store the names (paths) in an array and make a loop that changes the src property?
Thank you!
Try this demo: http://jsbin.com/pinoxeqapi/1/edit?html,output
I think that's what you're looking for.
CODE
$(function () {
var images = ["01.jpg", "01.jpg", "02.jpg", "03.jpg"];
$.each(images, function (index, element) {
var imgContainer = "<div class='row'><div class='col-md-3 col-xs-6 portfolio-item><img class='img-responsive' src='" + element + "'></div></div>";
$("body").append(imgContainer);
});
});
First Include JQuery (If not)
<script>
var srcArray = ['01.jpg', '02.jpg', '03.jpg', '04.jpg'];
$(document).ready(function () {
for (var i = 0; i < srcArray.length; i++) {
$('div.row img.img-responsive').eq(i).attr("src", srcArray[i]);
}
});
</script>
I would recommend using one of the templating frameworks described in some of the other answers. If you're interested to see how to implement this in pure JS:
var temp = document.querySelector('#portfolio-item-template');
['01.jpg', '02.jpg', '03.jpg', '04.jpg'].forEach(function(src) {
temp.content.querySelector(".img-responsive").src = src;
var newImg = document.importNode(temp.content, true);
document.querySelector('#insertion-point').appendChild(newImg);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<template id="portfolio-item-template">
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item">
<img class="img-responsive">
</div>
</div>
</template>
<div id="insertion-point">
</div>
You can use a template stored in the HTML and then generate the actual elements using an array of the image sources. Something like John Resig's micro-templates can achieve this.
<script type="text/template" id="img-tmpl">
<div class="row">
<div class="col-md-3 col-xs-6 portfolio-item>
<img class="img-responsive" src="<%= src %>">
</div>
</div>
</script>

AngularJS Loops and Formatting

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.

Categories

Resources