AngularJs - UI Bootstrap Popover - angularjs

Hello I'm using UI boostrap within Angular App
I would like to add Popover using UI boostrap, so this what I did so far:
<a popover popover-template="'tpl.html'" data-img="http://domain.com/img1.jpg" data-title="Link 1 title" data-content = "Link 1 content...">Link 1</a>
<a popover popover-template="'tpl.html'" data-img="http://domain.com/img2.jpg" data-title="Link 2 title" data-content = "Link 2 content...">Link 2</a>
...
<a popover popover-template="'tpl.html'" data-img="http://domain.com/imgn.jpg" data-title="Link n title" data-content = "Link n content...">Link n</a>
And then inject attributes : data-img, data-title, data-content in this template tpl.html:
<div class="popover-content">
<md-card>
<img ng-src="{{$img}}" class="md-card-image" >
<md-card-title>
<md-card-title-text>
<span class="md-headline">{{ $title}}</span>
</md-card-title-text>
</md-card-title>
<md-card-content>
{{ $content }}
</md-card-content>
</md-card>
</div>
Of course it doesn't work :)
My question is : how to inject element a attributes in the template tpl.html?
Please, any help is appreciated

Here's a plnkr showing how to use scope variable in the popover template.
Simplified markup & template:
<body ng-controller="MainCtrl">
<ul>
<li ng-repeat="link in links">
<a uib-popover popover-trigger="mouseenter" popover-placement="bottom" uib-popover-template="'tpl.html'" data-img="http://domain.com/img1.jpg" data-content = "Link 1 content...">{{link.label}}</a>
</li>
</ul>
<script type="text/ng-template" id="tpl.html">
<div class="popover-content">
<div>
<img ng-src="http://domain.com/{{link.img}}" class="md-card-image"/>
<div>
<span>{{link.title}}</span>
</div>
<div>{{ link.content }}</div>
</div>
</div>
</script>
Ctrl Code:
app.controller('MainCtrl', function($scope) {
$scope.links = [
{
label: 'Link 1',
title: 'Link 1 title',
content: 'Link 1 content',
img: 'img1.jpg'
},
{
label: 'Link 2',
title: 'Link 2 title',
content: 'Link 2 content',
img: 'img2.jpg'
},
{
label: 'Link 3',
title: 'Link 3 title',
content: 'Link 3 content',
img: 'img3.jpg'
}
];
});

Related

How to make expand and collapse manually child wise in angularjs

I have an accordion expand is working fine but collapse is not working,it should work like accordion,for ex when I click 'title 2' its content should expand and 'title 1' content should collapse.below is my code,I am new to angularjs.Anyone can help me.If its in jquery also fine.
HTML
<link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.css'>
<body ng-app="app">
<h1>Dynamic accordion: nested lists with html markup</h1>
<div ng-controller="AccordionDemoCtrl">
<div>
<div ng-repeat="group in groups">
<div class="parents" ng-click="item=1"><i class="glyphicon-plus"></i> {{ group.title }}
</div>
{{ group.content }}
<ul class="childs" ng-show="item==1">
<li ng-repeat="item in group.list">
<span ng-bind-html="item"></span>
</li>
</ul>
</div>
</div>
</div>
</body>
<script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.4/angular-filter.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular-sanitize.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap-tpls.js'></script>
<script src="js/index.js"></script>
index.js
angular.module('app', ['ui.bootstrap','ngSanitize','angular.filter']);
angular.module('app').controller('AccordionDemoCtrl', function ($scope) {
$scope.oneAtATime = true;
$scope.groups = [
{
title: 'title 1',
isOpen: true,
list: ['<i>item1a</i> blah blah',
'item2a',
'item3a']
},
{
title: 'title 2',
list: ['item1b',
'<b>item2b </b> blah ',
'item3b']
},
{
title: 'title 3',
},
{
title: 'title 4',
},
{
title: 'title 5',
}
];
});
I suggest you those functions :
$scope.open = function (index) {
$scope.groups[index].isOpen = !$scope.groups[index].isOpen;
$scope.closeOthers(index);
}
$scope.closeOthers = function (index) {
for(var i = 0; i < $scope.groups.length; i++) {
if (i !== index)
$scope.groups[i].isOpen = false;
}
}
open is fired when clicking on a parent, closeOthers is called in open. I init a visible boolean to parents. Each time user clicks on a parent, it set visible to true, and others to false.
<div ng-controller="AccordionDemoCtrl">
<div>
<div ng-repeat="group in groups track by $index">
<div class="parents" ng-click="open($index)"><i ng-class="{'glyphicon-minus': group.isOpen, 'glyphicon-plus': !group.isOpen}"></i> {{ group.title }}
</div>
{{ group.content }}
<ul class="childs" ng-show="group.isOpen">
<li ng-repeat="item in group.list">
<span ng-bind-html="item"></span>
</li>
</ul>
</div>
</div>
</div>
Working demo

How fire event when item expanded?

I use in my angularjs project bootstrap accordion.
Here is working plunker
When I expand accordion I want to fire function in my controller named fireOnExpand and pass the appropriate Id of the group to the function.
Here is how I use accordion:
<div ng-controller="MainCtrl">
<uib-accordion>
<uib-accordion-group heading="{{group.title}}" ng-repeat="group in groups" ng-init="isOpen = $first" is-open="isOpen">
<uib-accordion-heading>
<span ng-click="fireOnExpand()"></span>
<div class="text-center text-info">
<strong>{{group.title}}</strong>
</div>
</uib-accordion-heading>
{{group.content}} {{test}}
</uib-accordion-group>
</uib-accordion>
Here is items from controller that displayed:
$scope.groups = [
{Id: 5, title: "Dynamic-1", content: "Dynamic Group Body - 1"},
{Id: 8, title: "Dynamic-2", content: "Dynamic Group Body - 2"},
{Id: 1, title: "Dynamic-3", content: "Dynamic Group Body - 3"},
{Id: 3, title: "Dynamic-4", content: "Dynamic Group Body - 4"}];
Here the function in controller that I wont to fire on expand:
$scope.fireOnExpand = function()
{
alert("ParamPamPam");
};
For example:
If accordion item with header text "Dynamic-2" was expanded I want trigger fireOnExpand event handler and pass to the event appropriate Id(i.e. Id=8).
How can I fire function fireOnExpand and pass appropriate Id parameter when accordion item is expanded?
see Event Bubbling
change this
<span ng-click="fireOnExpand()"></span>
<div class="text-center text-info">
<strong>{{group.title}}</strong>
</div>
to
<span ng-click="fireOnExpand(group.Id)">
<div class="text-center text-info">
<strong>{{group.title}}</strong>
</div>
</span>
if you want to execute fireOnExpand on header text only, then move the ng-click to strong tag
<span>
<div class="text-center text-info">
<strong ng-click="fireOnExpand(group.Id)">{{group.title}}</strong>
</div>
</span>
Plunker
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('AccordionDemoCtrl', function ($scope) {
$scope.oneAtATime = true;
$scope.lastSelected= 0;
$scope.firstLoad =false;
$scope.groups = [{
Id:2,
title: "Dynamic Group Header - 1",
content: "Dynamic Group Body - 1"
}, {
Id:52,
title: "Dynamic Group Header - 2",
content: "Dynamic Group Body - 2"
}, {
Id:23,
title: "Dynamic Group Header - 3",
content: "Dynamic Group Body - 3",
},{
Id:78,
title: "Dynamic Group Header - 4",
content: "Dynamic Group Body - 4"
}];
$scope.fireOnExpand = function(id){
if ($scope.firstLoad === false){
if (id !== $scope.lastSelected || $scope.lastSelected !== 0){
$scope.lastSelected = id;
alert(id);
}
else {
alert("Do nothing");
}
$scope.firstLoad = true;
}
else {
if (id !== $scope.lastSelected ){
$scope.lastSelected = id;
alert(id);
}
else {
alert("Do nothing");
}
}
};
});
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-animate.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-1.3.2.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="AccordionDemoCtrl">
<uib-accordion close-others="oneAtATime">
<uib-accordion-group heading="{{group.title}}" ng-click="fireOnExpand($index)" ng-repeat="group in groups" is-open="$first">{{group.content}}</uib-accordion-group>
</uib-accordion>
</div>
</body>
</html>

How to escape an ng-Repeat loop?

I have the following ng-repeat loops that unpack JSON data into an Accordion:
<accordion close-others="oneAtATime">
<accordion-group ng-repeat="service in userPF.custom.services">
<accordion-heading><input type="checkbox" name="status" disabled>On <input type="checkbox" name="status" disabled checked>Off {{service.name}}</accordion-heading>
Related Items:<br>
<div class="secondary" ng-repeat="fields in userPF.custom.fields">
<span ng-show="checkForMatch(service.name, fields.services)">
<span ng-repeat="value in fields.values">
{{value.name}}<br>
</span>
</span>
</div>
</accordion-group>
</accordion>
The first trip through the loop {{service.name}} will always return data but the second value {{value.name}} might not. If it doesn't I don't want the div or span to render, just the heading. I've tried some variations on ng-if but haven't come close to being able to tell if I'm getting data back or not.
Refer this Link.
AS this code shows and its working fine you can have ng-show inside ng-repeat.
<div ng-app ng-controller="RepeatTestCtrl">
<ul ng-repeat="item in items">
<li ng-show="item.id.length == 0">{{item.name}} is even</li>
<li ng-show="item.id % 2 == 1">{{item.name}} is odd</li>
</ul>
</div>
function RepeatTestCtrl($scope) {
$scope.items = [
{ id: 1, name: 'test 1' },
{ id: 2, name: 'test 2' },
{ id: 3, name: 'test 3' },
{ id: 4, name: 'test 4' }
];
}
http://jsfiddle.net/b004t06z/41/

How to handle selected/unselected ng-class to manage a tabbed popover

My code is as follows (the fiddle):
<div ng-controller="myCtrl">
<div ng-model="currentTab" ng-init="currentTab='Tab1'"/>
<div ng-init="popovers = [
{ name: 'Popover1',
displayName: 'Pop over with two tabs',
tabs: [
{ name: 'Tab1',
displayName: 'First tab',
description: ['First tab description']
},
{ name: 'Tab2',
displayName: 'Second tab',
description: ['Second tab description']
}
]
}
]"/>
<b>Tabs in popover</b>
<div
class="popover"
ng-repeat="p in popovers"
>
Popover name: {{p.displayName}}
<div ng-repeat="t in p.tabs"
class="tab"
ng-class="currentTab==t.name?'selected':''"
ng-click="currentTab=t.name"
>
{{t.name}}
</div>
<div ng-repeat="t in p.tabs"
class="tabContent"
ng-class="currentTab==t.name?'selected':''"
>
<p>{{t.displayName}}</p>
</div>
</div>
</div>
There is something I don't get which make the code not working perfectly, as the selected class name is never removed as one click on the tab.
When you want to modify a variable of your parent scope from within a ng-repeat you need to use $parent.currentTab.
Updated Fiddle

How do I make the carousel indicators in angular ui use thumbnails from a model in a controller?

I'm using the angular ui bootstrap carousel and I want to make the indicators thumbnails. I have a controller that looks like this (from the demo):
function carouselCtrl($scope) {
$scope.myInterval = 5000;
$scope.imgPath="img/slideshow/"
var slides = $scope.slides = [{
'imgName':'iguanas.jpg',
'caption':'Marine iguanas in the Galapagos National Park on Santa Cruz Island, on September 15, 2008.',
'author':'(Reuters/Guillermo Granja)'
},{
'imgName':'eruption.jpg',
'caption':'In June of 2009, the Cerro Azul volcano on Isabela Island was in an active phase, spewing molten lava into the air, spilling it across its flanks, and widening existing lava flows.',
'author':'(Reuters/Parque Nacional Galapagos)'
},{
'imgName':'bluefoot.jpg',
'caption':'A close-up of a pair of Booby feet, photographed in March of 2008. ',
'author':'(CC BY Michael McCullough)'
}];
}
and the template looks like this:
<div ng-mouseenter="pause()" ng-mouseleave="play()" class="carousel">
<ul class="carousel-indicators" ng-show="slides().length > 1">
<li ng-repeat="slide in slides()" class="slide-thumb" ng-class="{active: isActive(slide)}" ng-click="select(slide)"></li>
</ul>
<div class="carousel-inner" ng-transclude></div>
<a ng-click="prev()" class="carousel-control left" ng-show="slides().length > 1">‹</a>
<a ng-click="next()" class="carousel-control right" ng-show="slides().length > 1">›</a>
</div>
I want to do something like this:
<li ng-repeat="slide in slides()" class="slide-thumb" ng-class="{active: isActive(slide)}" ng-click="select(slide)" style="background-image:url({{slide.imgName}});"></li>
but I must be out of scope or something... Does anyone know any angular carousels that have a thumbnail option or how I can get this to work?
The slide array in the carousel template actually don't refer to the slides array you have defined in your app controller.
In the carousel template slides refer to a bunch of dom elements enhanced with internal properties. That's why any access to properties you have defined in our objects will failed when executed (scope issue as you guessed already).
If you want to stick to the carousel from angular-ui I would recommend a slightly different approach and go for css styling something like that:
//Default styles for indicator elements
.carousel-indicators li {
background-size : 42px 22px;
width : 42px;
height: 22px;
background-repeat : no-repeat;
background-position : center;
cursor : pointer;
}
// Then Specify a background image for every slide
.carousel-indicators li:nth-child(1){
background-image: url(http://cache.wallpaperdownloader.com/bing/img/WeddedRocks_20100418.jpg);
}
...
You can see a working Plunker here.
It's very possible and it's very simple. First you must pass the model of every slide in the actual directive as indicated in the docs for the uib-slide settings. And then you must override the template using the template-url directive. Don't forget to declare the template.
So the html should look like this:
<!--Defining the controller scope-->
<div ng-controller="carousel">
<!--Declaring the template for later usage-->
<script id="carousel-with-thumbs.html" type="text/ng-template">
<div ng-mouseenter="pause()" ng-mouseleave="play()" class="carousel" ng-swipe-right="prev()"
ng-swipe-left="next()">
<div class="carousel-inner" ng-transclude></div>
<a role="button" href class="left carousel-control" ng-click="prev()"
ng-class="{ disabled: isPrevDisabled() }"
ng-show="slides.length > 1">
<span aria-hidden="true" class="glyphicon glyphicon-chevron-left"></span>
<span class="sr-only">previous</span>
</a>
<a role="button" href class="right carousel-control" ng-click="next()"
ng-class="{ disabled: isNextDisabled() }"
ng-show="slides.length > 1">
<span aria-hidden="true" class="glyphicon glyphicon-chevron-right"></span>
<span class="sr-only">next</span>
</a>
<ol class="carousel-indicators" ng-show="slides.length > 1">
<li ng-repeat="slide in slides | orderBy:indexOfSlide track by $index"
ng-class="{ active: isActive(slide) }" ng-click="select(slide)">
<!--Showing the thumbnail in a <img> tag -->
<img ng-src="{{slide.slide.actual.thumb}}">
<span class="sr-only">slide {{ $index + 1 }} of {{ slides.length }}<span ng-if="isActive(slide)">, currently active</span></span>
</li>
</ol>
</div>
</div>
</script>
<uib-carousel active="active" interval="interval" template-url="carousel-with-thumbs.html">
<uib-slide ng-repeat="slide in slides track by $index" index="$index" actual="slide">
<!--Passing the slide in the actual directive-->
<img ng-src="{{slide.image}}" style="margin:auto;">
<div class="carousel-caption">
<h4>{{slide.title}}</h4>
<p>{{slide.text}}</p>
</div>
</uib-slide>
</uib-carousel>
Take a moment to analyse the carousel-indicators ordered list:
<ol class="carousel-indicators" ng-show="slides.length > 1">
<li ng-repeat="slide in slides | orderBy:indexOfSlide track by $index" ng-class="{ active: isActive(slide) }"
ng-click="select(slide)">
<img ng-src="{{slide.slide.actual.thumb}}">
<span class="sr-only">slide {{ $index + 1 }} of {{ slides.length }}<span ng-if="isActive(slide)">, currently active</span></span>
</li>
</ol>
Look how each slide model has another slide sub-model which is the transcluded scope of the slide model passed
through the actual directive. And then, nested again, the actual model containing all the data of each slide:
<img ng-src="{{slide.slide.actual.thumb}}">
And of course for the big finale, the controller should look like this:
(function(){
'use strict';
angular
.module('app', ['ui.bootstrap'])
.controller('carousel', carousel);
carousel.$inject = ['$scope'];
function carousel($scope){
$scope.active = 0;
$scope.interval = 5000;
$scope.slides = [
{title: "Any title", text: "This is a text for the slide", image: "path/to/the/image/image.jpg", thumb: "path/to/the/image/thumbs/thumb.jpg"},
{title: "Any title", text: "This is a text for the slide", image: "path/to/the/image/image.jpg", thumb: "path/to/the/image/thumbs/thumb.jpg"},
{title: "Any title", text: "This is a text for the slide", image: "path/to/the/image/image.jpg", thumb: "path/to/the/image/thumbs/thumb.jpg"}
];
}
})();
By the way, I'm using Angular UI Boostrap 1.3.3 along with Angular 1.5.8.
Here's the Fiddle for it https://jsfiddle.net/logus/6mvjpf40/

Resources