How fire event when item expanded? - angularjs

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>

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

Angularjs: how to pass $filter to function in case of "controller as" syntax?

I am new to AngularJS. I am trying to work out an example of a SportsStore app from a book I am following.
In this app, there are several categories of products. Categories are also displayed on the left side of the view.
Clicking a "category" is going to filter the products by category and is going to highlight the Category button.
Reading tutorials on net I understand that the "controller as" syntax is being favored over the "$scope" syntax.
How do I pass a filter (categoryFilterFn) to my controller function for filtering the products by category?
app.html
<!DOCTYPE html>
<html ng-app="SportsStoreApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular-resource.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.css" rel="stylesheet" />
<script src='app.js'></script>
<script src='customFilters.js'></script>
<script src='productListControllers.js'></script>
</head>
<body ng-controller="SportsStoreCtrl as controller">
<div class="navbar navbar-inverse">
<a class="navbar-brand" href="#">SPORTS STORE</a>
</div>
<div class="panel panel-default row" ng-controller="ProductListCtrl">
<div class="col-xs-3">
<a ng-click="selectCategory()"
class="btn btn-block btn-default btn-lg">Home</a>
<a ng-repeat="item in controller.data.products | orderBy:'category' | unique_selection:'category'"
ng-click="selectCategory(item)" class=" btn btn-block btn-default btn-lg"
ng-class="getCategoryClass(item)">
{{item}}
</a>
</div>
<div class="col-xs-8">
<div class="well" ng-repeat="item in controller.data.products | filter:categoryFilterFn">
<h3>
<strong>{{item.name}}</strong>
<span class="pull-right label label-primary">
{{item.price | currency}}
</span>
</h3>
<span class="lead">{{item.description}}</span>
</div>
</div>
</div>
</body>
</html>
customFilters.js
angular.module("customFilters", [])
.filter("unique_selection", function(){
return function(data, propertyName) {
if (angular.isArray(data) && angular.isString(propertyName)) {
var results = [];
var keys = {};
for (var i = 0; i < data.length; i++) {
var val = data[i][propertyName];
if (angular.isUndefined(keys[val])) {
keys[val] = true;
results.push(val);
}
}
return results;
} else {
return data;
}
}
});
app.js
var app = angular.module("SportsStoreApp", ['customFilters']);
app.controller("SportsStoreCtrl", function(){
this.data = {
products: [
{ name: "Product #1", description: "A product",
category: "Category #1", price: 100 },
{ name: "Product #2", description: "A product",
category: "Category #1", price: 110 },
{ name: "Product #3", description: "A product",
category: "Category #2", price: 210 },
{ name: "Product #4", description: "A product",
category: "Category #3", price: 202 }
]
};
});
productListControllers.js
angular.module("SportsStoreApp")
.constant('productListActiveClass', "btn-primary")
.controller('ProductListCtrl', function($scope, $filter, productListActiveClass) {
var selectedCategory = null;
$scope.selectCategory = function(newCategory) {
selectedCategory = newCategory;
};
$scope.categoryFilterFn = function(product) {
return selectedCategory == null ||
product.category == selectedCategory;
};
$scope.getCategoryClass = function(category) {
return selectedCategory = category ? productListActiveClass : "";
};
});
In productListControllers.js, how do I not use "$scope" object and use "this" object along with "$filter" argument? Also, how can I use "ProductListCtrl as product_ctrl" in app.html?
If you want to use your custom filter inside a controller, simply inject your custom filter into your controller using the name of your filter and the suffix Filter.
In your instance you need to inject unique_selectionFilter. You can then use it in your controller passing in your data and property name values:
unique_selectionFilter(data, propertyName)
Alternatively you can inject the $filter service and access your filter through it by passing in it's name:
$filter('unique_selection')(data, propertyName)

Show a part of option or shorthand of option content in select tag

I was wondering about the way to display part of the option content or abbreviation of option content in select tag when an option get selected.
For example: I have following option in select tag-
India(IN)
China(CN)
Brazil(BR)
If India is selected from the options list then select tag show IN not India.
Does is possible to do using angularjs? Please suggest.
You can do it with angularui bootstrap's dropdown.
I assume you have country object as {name:, code:}
// Code goes here
var app = angular.module("app",['ui.bootstrap'])
app.controller("ctrl", function($scope){
$scope.title = "dropdown demo";
$scope.items = [
{name: "India", code:"IN"},
{name: "Canada", code:"CA"},
{name: "United Kingdom", code:"UK"}
];
$scope.selected = null;
$scope.selectOption = function(c){
$scope.selected = c;
}
})
<link data-require="bootstrap#*" data-semver="4.0.0-alpha.2" rel="stylesheet" href="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/css/bootstrap.css" />
<script data-require="bootstrap#*" data-semver="4.0.0-alpha.2" src="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/js/bootstrap.js"></script>
<script data-require="angularjs#1.4.9" data-semver="1.4.9" src="https://code.angularjs.org/1.4.9/angular.min.js"></script>
<script data-require="ui-bootstrap#1.2.5" data-semver="1.2.5" src="https://cdn.rawgit.com/angular-ui/bootstrap/gh-pages/ui-bootstrap-1.2.5.js"></script>
<div ng-app ="app" ng-controller="ctrl">
<h1>{{title}}</h1>
<span uib-dropdown="">
<a href="" id="simple-dropdown" uib-dropdown-toggle="">
{{selected.code || "select Country"}}
</a>
<ul class="dropdown-menu" uib-dropdown-menu="" aria-labelledby="simple-dropdown">
<li ng-repeat="c in items">
<a ng-click="selectOption(c)">{{c.name}} ({{c.code}})</a>
</li>
</ul>
</span>
</div>
added script

AngularJs - UI Bootstrap Popover

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'
}
];
});

How to include an additional element in ng-repeat at a specific index location?

<!-- if (index == 2) <div>{{data.customText}}</div> -->
<div ng-repeat-start="product in products">{{product.headline}}</div>
<div ng-repeat-end>{{product.text}}</div>
Let's assume I'm showing 5 products, and I want to display additional content {{product.customText}} on 3rd position in between. How could I achieve this?
Use $index attribute and ng-show for showing conditional element. For example the following will be shown only for the 3rd element
var myApp = angular.module("myApp", []);
myApp.controller("MyCtrl", ["$scope",
function($scope) {
$scope.products = [{
headline: "headline1",
text: "text 1"
}, {
headline: "headline2",
text: "text 2"
}, {
headline: "headline3",
text: "text 3"
}, {
headline: "headline4",
text: "text 4"
}, {
headline: "headline5",
text: "text 5"
}];
$scope.data = {
customText: "customText"
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html>
<body ng-app="myApp">
<div ng-controller="MyCtrl">
<span ng-repeat="product in products">
<div ng-show="$index == 2">{{data.customText}}</div>
<div>{{product.headline}}</div>
<div>{{product.text}}</div>
</span>
</div>
</body>
</html>
You can use $index to do so.
<div ng-repeat-start="product in products">{{product.headline}}</div>
<div ng-if="$index == 2">{{product.customText}}</div>
<div ng-repeat-end>{{product.text}}</div>

Resources