AngularJS - Using ng-switch in ng-repeat to conditionally apply HTML - javascript

I have a paginated list of video thumbnails I want to display in a Bootstrap fluid grid. I'm using a nested ng-repeat to first iterate over each list, for pagination, and an inner ng-repeat to iterate over each video thumbnail in the subarray. The grid is 3x6 so when the inner ng-repeat's index is a multiple of 5 (assuming $index starts at 0), I want to close a fluid row and start a new one.
<div ng-repeat="thumbList in thumbLists">
<div ng-repeat="thumb in thumbList" class="row-fluid">
<div class="span2">
<a href="{{ thumb.URL }}">
<img src="{{ thumb.thumbnailURL }}" width="160" height="85" alt="" class="img-responsive">
</a>
</div>
<!-- ng-switch? -->
</div>
</div>
The lists are populated by a REST service, such that when a user clicks on a 'next' button, a new array list' is pushed onto the 'lists' and an animation will slide over each 3x6 grid. The structure looks like:
$scope.thumbLists = [
[{URL: url, thumbnailURL: thumburl}, ...], // init
[{URL: url, thumbnailURL: thumburl}, ...], // pushed when user clicks 'next'
... etc
];
Everything I have is working properly, I'm just not sure how to conditionally add in the HTML to close a row and start a new one once that row hits 6 since the thumbnails are given in a single array.
For example, where I have the commented ng-switch, could I do something like:
<div ng-switch="$index">
<div ng-switch-when="$index % 6 == 5">
</div>
Using 1.0.8 stable release. Must support IE8.
Temporary solution - removing the left margin for each element that is the first in it's row:
<div ng-repeat="thumbList in thumbLists">
<div class="row-fluid>
<div ng-repeat="thumb in thumbList" class="span2" ng-class="{nomargin: $index % 6 == 0}">
<a href="{{ thumb.URL }}">
<img src="{{ thumb.thumbnailURL }}" width="160" height="85" alt="" class="img-responsive">
</a>
</div>
</div>
</div>
Would still like to find a solution that where I can conditionally insert/remove HTML, perhaps using a directive.

Would ng-grid work for you? Might save you having to deal with the details.
http://angular-ui.github.io/ng-grid/

This works with ng-switch -- but may need some more tweaking to avoid the extra hidden span markup...
<div ng-repeat="thumb in thumbList">
<span ng-switch="$index % 5">
<div class="row" ng-switch-when="0">
<div class="col-sm-2"><img src="{{thumbList[$index+0].url}}" class="img-responsive"></div>
<div class="col-sm-2"><img src="{{thumbList[$index+1].url}}" class="img-responsive"></div>
<div class="col-sm-2"><img src="{{thumbList[$index+2].url}}" class="img-responsive"></div>
<div class="col-sm-2"><img src="{{thumbList[$index+1].url}}" class="img-responsive"></div>
<div class="col-sm-2"><img src="{{thumbList[$index+2].url}}" class="img-responsive"></div>
</div>
</span>
</div>
http://bootply.com/86985

Related

Image Gallery - Slider

I developed an image gallery. In a main box (large box) I introduce the first image of the array, the rest are arranged horizontally below that image.
Is there a way to get the big box to function as an image slider?
At this point try to apply, however I have some problems :( the secondary images do not appear below the main one, nor is the slider working correctly, when I move to the second image, all the others are loaded.
I chose to use * ngFor to load secondary images, in case I can have an array with indeterminate quantities of images.
DEMO
CODE
<div class="col-md-6">
<div class="drop">
<div class="abc">
<img class="img-fluid Images" [src]="images[0].img" >
</div>
</div>
<div class="row">
<div class="Upcard" *ngFor="let img of images | slice:1" cdkDrag>
<img class="img-thumbnail" [src]="img.img" style="width: 100%; height: 100%;">
</div>
</div>
</div>
<!-- -------------------------------SLIDER----------- -->
<div class="col-md-6">
<ngb-carousel *ngIf="images">
<div class="drop">
<div class="abc">
<ng-template ngbSlide>
<img [src]="images[0].img" alt="Random first slide">
</ng-template>
</div>
</div>
<ng-template ngbSlide>
<div class="row">
<div class="Upcard" *ngFor="let img of images | slice:1" cdkDrag>
<img class="img-thumbnail" [src]="img.img" style="width: 100%; height: 100%;">
</div>
</div>
</ng-template>
</ngb-carousel>
</div>
What I want with the functional slider
I intend that when clicking on the buttons on the slider it will display the secondary images (the images shown below the main image)
you have to use corousel-Api to get change event.
corousel emit slide event when image is change(automatic or via button)
so you have to add an event to corousel change i have added change($event) to (slide) output.
<ngb-carousel id="carousel" #carouse *ngIf="data" (slide)="change($event)" >
<ng-template *ngFor="let imgIdx of data; let i = index" [id]="i" ngbSlide>
<div class="picsum-img-wrapper">
<img [src]="imgIdx.image" [alt]="">
</div>
<div class="carousel-caption">
<h3>{{imgIdx.head}}</h3>
<p>{{imgIdx.data}}</p>
</div>
</ng-template>
</ngb-carousel>
<div *ngFor="let imgIdx of belowImageData; let i = index" style="width:80px" >
<img class="col-sm" [src]="imgIdx.image" style="width: 100%; height: 100%;">
</div>
then in chnage event i have updated belowImageData array according to image loded in upper corousel.
constructor(){
this.belowImageData = JSON.parse(JSON.stringify(this.data));
this.belowImageData.splice(0,1);
}
change(data){
console.log(data.current)
this.belowImageData = JSON.parse(JSON.stringify(this.data));
this.belowImageData.splice(data.current, 1);
}
you can also add this line to pause automatic slide
this.carousel.pause();
i have developed a stackblitz for you(without proper css).

Need help in fixing and creating carousel js functions or css styles (Angular 6)

I'm having a problem creating and fixing carousel animations. Most carousels are only in 1 per screen while I need 4 per screen so I'm trying to implement my own carousel.
Current html:
<div class="display-flex m-t-2">
<div [ngClass]="{ 'disabled-button': page === 1, 'cursor-pointer': page > 1}" (click)="prev()">
<i class="material-icons">keyboard_arrow_left</i>
</div>
<div class="display-flex-child width-100">
<div class="m-x-2" *ngFor="let prod of productList">
<div class="display-flex flex-direction">
<div class="text-title">{{prod.title}}</div>
<div>
<img [src]="prod.url" alt="{{prod.title}}" height="200" width="200">
</div>
</div>
</div>
</div>
<div [ngClass]="{ 'justify-content-right disabled-button': !hasNextValues,
'justify-content-right cursor-pointer': hasNextValues}" (click)="next()">
<i class="material-icons">keyboard_arrow_right</i>
</div>
</div>
Image here:
Html code result image
Expected: to be like a carousel that has a delay when clicking next and previous button
Actual: instantly goes to next or previous

How to calculate a transaction in ng-if and put a `<div>` only if the condition is true?

i want to add a row only if the x in $scope.grp leaves no remainder when divided by 3. I was trying the following code.
<div class="card">
<div ng-repeat="x in grp">
<div class="row">
<div ng-if="x%3==0">
<div class="row">
</div>
<div class="col col-33">
/my rest of code here/
</div>
</div>
</div>
<div>
any suggestions how to do it?
Not sure whether the following is correct or not. But a way to achieve it is as following.
<div data-ng-app="" data-ng-init="grp=['one','two','three','four','five','six','seven']" class="container">
<div ng-repeat="x in grp" ng-if="$index % 3 == 0" class="row">
<div class="col-xs-3">{{grp[$index]}}</div>
<div class="col-xs-3" ng-if="$index + 1 < grp.length">{{grp[$index+1]}}</div>
<div class="col-xs-3" ng-if="$index + 2 < grp.length">{{grp[$index+2]}}</div>
</div>
<div>
I am assuming grp is a string array and used $index to group.
Jsfiddle
Check this:
if reminder is 0, row will be added
<div class="card">
<div ng-repeat="x in grp">
<div class="row">
<div ng-if="x%3==0">
<div class="row">
reminder 0
</div>
</div>
<div class="col col-33">
my rest of code here
</div>
</div>
</div>
Here is the code for controller
function ctrl($scope){
$scope.grp=[1,2,3];
}
Codepen : http://codepen.io/anon/pen/eJJKwr
I'm not very familiar with angularjs - however your html struct is wrong in this case. Your struct will create an empty "row" column before every third div. I don't know if there is a way to just open a "div" tag in an ng-if and close it at a later point.
You should consider just creating array chunks for your cards. So each chunk will hold 3 cards and then you can loop over the first level of chunks, and then over the second level of your array. It will look something like that:
<div class="card">
<div ng-repeat="grp in chunks">
<div class="row">
<div ng-repeat"x in grp"> // as mentioned, I got no clue about angularjs, so I don't know how to correctly address the values within the groups
<div class="col col-33">
my rest of code here
</div>
</div>
</div>
</div>
</div>
As mentioned before I have no clue about angularjs itself, however you should be able to create chunks (split your array into smaller arrays) like:
var chunks=[[1,2,3],[4,5,6],[7,8,9]];

Cleaning up Angular Partials

I am making a menu that has a few different types of buttons with AngularJS. Based on the type of button, the html needs to have different characteristics. Also, the currently selected menu item needs to have a different color than the available buttons. Currently, I am using this mess of code:
<div id="navbar" ng-show="navbar.show" ng-mouseenter="navbar.keep()" ng-mouseleave="navbar.release()">
<div ng-repeat="navSection in navbar.navSections" ng-init="sectionIndex = $index" class="navblock">
<div ng-repeat="navItem in navSection.navigationItems">
<div ng-switch on="navItem.function">
<div ng-switch-when='CategoryNav', ng-click='navbar.navClick(sectionIndex, $index)'>
<div info="navItem", ng-if='sectionIndex == navbar.section && $index == navbar.item', id="selected">
<a ui-sref="{{navItem.function}}" ng-href="{{navItem.function}}">
<div class="navbutton">{{navItem.label}}</div>
</a>
</div>
<div info="navItem", ng-if='sectionIndex != navbar.section || $index != navbar.item', id="notselected">
<a ui-sref="{{navItem.function}}" ng-href="{{navItem.function}}">
<div class="navbutton">{{navItem.label}}</div>
</a>
</div>
</div>
<div ng-switch-when='StorefrontNav', ng-click='navbar.changeStorefront(navItem.type)'>
<div info="navItem", id="notselected">
<a ui-sref="{{navItem.function}}" ng-href="{{navItem.function}}">
<div class="navbutton">{{navItem.label}}</div>
</a>
</div>
</div>
<div ng-switch-default>
<div info="navItem", ng-if='sectionIndex == navbar.section && $index == navbar.item', id="selected">
<a ui-sref="{{navItem.function}}" ng-href="{{navItem.function}}">
<div class="navbutton">{{navItem.label}}</div>
</a>
</div>
<div info="navItem", ng-if='sectionIndex != navbar.section || $index != navbar.item', id="notselected">
<a ui-sref="{{navItem.function}}" ng-href="{{navItem.function}}">
<div class="navbutton">{{navItem.label}}</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
It works fine but I want to clean it up a little bit. I have thought about making a directive and passing in the functions the different links need to work (for example, the navbar.changeStoreFront()) but that seems like a lot of extra code just to clean the format up a bit. Does anyone know any better ways of cleaning this up?
I noticed that the simplest way to make the code more readable is to put the attributes on separate lines. Take this for example:
<ui-gmap-google-map center='{expression}'
control='{Object}'
zoom='{expression}'
dragging='{expression}'
refresh='{expression}'
options='{expression}'
events='{expression}'
bounds='{expression}'
pan='{string or boolean}'
>
<!-- other ui-gmap-directives here -->
</ui-gmap-google-map>

jQuery - Having the same HTML twice renders my script inoperative

I'm quite new to jQuery and I have come up with script which affects the HTML below. The script works perfectly and I have gotten it to whether I would like. The problem I am having
is when I'm duplicating the HTML and the script, once clicked, only shows the last project-info and project-images within the document. I've tried quite a few different methods just as
$(this).children()
but I can't seem to get any to work. Any help would be much appreciated.
Thank you
jQuery
$(document).ready(function() {
$('.apple').click(function() {
$('#darken').addClass('dark');
$('.project-info').delay('1000').slideDown('slow');
$('.project-images').delay('1000').fadeIn('slow');
});
});
$(document).ready(function() {
$('.close').click(function() {
$(".project-info, .project-images").fadeOut('slow');
});
});
HTML
<div class="apple">
<img src="http://mybroadband.co.za/photos/data/500/apple-logo.jpg"/>
</div>
<div class="project-info" style="display:none;">
<div class="project-title">
<h1>hello world</h1>
</div>
<div class="details">
<p>dkusdufhu suskueh sukh suefhuksdfnkuesnfukneukf nseuknfukenfuk nukefnuksn fukfuksukfnuksenf unseukfunfukfunufen u u u ef euhfuehfeufu g gfd gerjkg rjgrjg j js grg rgsg dkusdufhu suskueh sukh</p>
<div class="links">
link
</div>
<div class="close"></div>
</div><!-- end of project info -->
</div>
<div class="project-images" style="display:none;">
<div class="-images">
<img src="http://cdn4.spiegel.de/images/image-499233-galleryV9-grcy.jpg" />
<img src="http://cdn4.spiegel.de/images/image-499233-galleryV9-grcy.jpg" />
</div>
<div class="close end"></div>
</div> <!-- Project Images -->
</div> <!-- # Darken -- >
You're nearly there. Children wouldn't work in the above example because the divs with class 'apple' don't have any children. You need to move that first closing tag to the bottom of the portfolio item so that your html for each portfolio item is structured like this:
<!--PORTFOLIO ITEM-->
<div class="apple">
<!-- ICON GOES HERE-->
<img src="http://mybroadband.co.za/photos/data/500/apple-logo.jpg"/>
<!-- PROJECT INFO GOES HERE-->
<div class="project-info" style="display:none;">
</div>
<!-- PROJECT IMAGES GOES HERE-->
<div class="project-images" style="display:none;">
</div>
</div>
I.e. the divs with classes 'project-info' and 'project-images' are inside the 'apple' div. Then change this:
$('.project-info').delay('1000').slideDown('slow');
$('.project-images').delay('1000').fadeIn('slow');
to this:
$(this).children('.project-info').delay('1000').slideDown('slow');
$(this).children('.project-images',this).delay('1000').fadeIn('slow');
If you've updated your html correctly, $(this) will be pointing to a div element that does indeed have children with classes 'project-info' and 'project-images'. Here's an updated JSFiddle that should do you what you want: http://jsfiddle.net/8k3Ms/1/

Categories