Using bootstrap collapse with angularjs - angularjs

I'm trying to include the below bootstrap collapsible panel in my angular application. However, when I click on "Expand", angular seems to see href="#collapseOne" and then redirects to the home page instead of collapsing the panel. My routing looks like this, and I think the otherwise({redirectTo: '/home'}); is causing the problem. Any suggestions?
angular.module('App')
.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/users', {templateUrl: 'partials/users/user-list.html', controller: 'UserCtrl'}).
when('/users/new', {templateUrl: 'partials/users/user-new.html', controller: 'UserNewCtrl'}).
when('/users/:userid', {templateUrl: 'partials/users/user-detail.html', controller: 'UserDetailCtrl'}).
otherwise({redirectTo: '/home'});
}]);
The panel-
<div class="panel-group" id="accordion">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
Expand
</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse in">
<div class="panel-body">
...
</div>
</div>
</div>
</div>

As mentionned in a similar question Here, simply change your href by the data-target attribute
<div class="panel-group" id="accordion">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a href="javascript:;" data-toggle="collapse" data-parent="#accordion" data-target="#collapseOne">
Expand
</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse in">
<div class="panel-body">
...
</div>
</div>
</div>
</div>

You can use the accordion directive from AngularJS UI Bootstrap that builds on top of twitter bootstrap the collapse directive.
example:
<accordion >
<accordion-group heading="Static Header, initially expanded" is-open="true">
This content is straight in the template.
</accordion-group>
</accordion>
Live example: http://jsfiddle.net/choroshin/U89bW/3/

I had the same issue, and I didn't want to add an additional library beyond bootstrap. As recommended, you can usedata-target="#your-collapsing-element", removing the href attribute completely.
The basics
To make a panel collapse you need:
On the element used to trigger collapse:
data-toggle="collapse" data-target="#my-collapsing-element"
On the element that collapses:
id="my-collapsing-element"
On the element wrapping both the "trigger" element and the collapsing element:
class="panel"
Putting it all together
You can optionally add parent elements to make it part of a group, and add add the css classes "collapse in" to the collapsing element to make its default state closed. A full example:
<div id="accordion">
<div class="panel">
<a data-toggle="collapse" data-parent="#accordion" data-target="#collapse1">
Heading 1
</a>
<div id="collapse1">
Content for panel 1
</div>
</div>
<div class="panel">
<a data-toggle="collapse" data-parent="#accordion" data-target="#collapse2">
Heading 2
</a>
<div id="collapse2" class="collapse in">
Content for panel 2
</div>
</div>
</div>
You can get better button behaviors by using a <button> element rather than an <a>. Overriding bootstrap's styling for .panel can be done by adding your own styling for the panel css class.
<div class="panel its-my-panel">
.panel.its-my-panel {
margin-bottom: 0;
background-color: transparent;
border: none;
border-radius: 0;
-webkit-box-shadow: none;
box-shadow: none;
}
.my-panel-heading {
cursor: pointer;
}
/* Overrides for .panel--theonly required bootstrap class */
.panel.my-panel-overrides {
margin-bottom: 0;
background-color: transparent;
border: none;
border-radius: 0;
-webkit-box-shadow: none;
box-shadow: none;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<div id="accordion">
<div class="panel my-panel-overrides">
<a class="my-panel-heading" data-toggle="collapse" data-parent="#accordion" data-target="#collapse1">
Collapsible Group 1</a>
<div id="collapse1" class="collapse in">
Content for panel 1
</div>
</div>
<div class="panel my-panel-overrides">
<a class="my-panel-heading" data-toggle="collapse" data-parent="#accordion" data-target="#collapse2">
Collapsible Group 2</a>
<div id="collapse2" class="collapse">
Content for panel 2
</div>
</div>
<div class="panel my-panel-overrides">
<a class="my-panel-heading" data-toggle="collapse" data-parent="#accordion" data-target="#collapse3">
Collapsible Group 3</a>
<div id="collapse3" class="collapse">
Content for panel 3
</div>
</div>
</div>

Change all href in order to expand-collapse to data-target.
data-target and id of the div to be expanded and collapsed should not contain hyphen.

Click the buttons below to show and hide another element via class changes:
collapse hides content
collapsing is applied during transitions
collapse.in shows content
You can use a link with the href attribute, or a button with the data-target attribute. In both cases, the data-toggle="collapse" is required.
check this example below.
Bootsrap Example
<div class="panel-group" id="accordion">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a href="javascript:;" data-toggle="collapse" data-parent="#accordion" data-target="#collapseOne">
Expand
</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse in">
<div class="panel-body">
...
</div>
</div>

Related

connect accordian heading and body through href and id

I have created a bootstrap accordian. When i click an accordian heading, it should show the body contents. I am providing the values dynamically(scope variable) for href and id attributes using angularjs.
But this is not working??
<div class="panel-group col-lg-3" style="background-color:#505054;height:450px" id="accordion">
<div class="panel" style="background-color:#505054;color:#C1C1C1;border-bottom: 1px solid #eee;">
<h6>Clear Filter</h6>
</div>
<div class="panel" style="background-color:#505054;color:white;border-bottom: 1px solid white;" ng-repeat="prdlines in detpline">
<div class="panel-heading">
<h6>
<div class="accordion-toggle" style="cursor:pointer" data-toggle="collapse" data-parent="#accordion" ng-click="plfilter(prdlines.id)" ng-href="{{prdlines.productline_name}}">{{prdlines.productline_name}}</div>
</h6>
</div>
<div ng-attr-id="{{prdlines.productline_name}}" class="panel-collapse collapse">
<div class="panel-body">
<ul id="style-3" style="height:200px; overflow: auto;cursor:pointer">
<li class="panel-title" ng-repeat="prd in detprd"><a ng-click="cfilter(prd.product_name)"><h5>{{prd.product_name}}</h5></a></li>
</ul>
</div>
</div>
</div>
</div>
What is the syntax problem?
For accordian you don't need to specify href and id. Use UI bootstrap.
https://angular-ui.github.io/bootstrap/#/accordion
http://embed.plnkr.co/3y0Rq1/

syntax to use binding expression inside href

I have created a nested accordian bootstrap panel. On clicking the parent(top most) panel heading - dropdown works fine but on clicking the child(sub panel heading) panel heading-dropdown wont work. I am retriving panel contents(sub panel heading and body) using angular $http.get rest api.
In this case, i think i did a mistake in syntax while linking the panel heading and panel body with its href and id attribute values( ng-href="{{productline_name}}" and id="{{productline_name}}" ).
Below code is placed inside top most panel body to create nested panel
<div class="panel-group col-lg-3" style="background-color:#505054;height:450px" id="accordion">
<div class="panel" style="background-color:#505054;color:#C1C1C1;border-bottom: 1px solid #eee;">
<h6>Clear Filter</h6>
</div>
<div class="panel" style="background-color:#505054;color:white;border-bottom: 1px solid white;">
<div class="panel-heading">
<h6>
<div class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapse1">PRODUCT</div>
</h6>
</div>
<div id="collapse1" class="panel-collapse collapse in">
<div class="panel-body">
<ul>
<li class="panel-title"><a ng-click="cfilter('all')"><h5>All Records</h5></a></li>
<li ng-repeat="pline in detpline" class="panel-group" id="accordion2">
<div class="panel" style="background-color:#505054;color:white;border-bottom: 1px solid white;">
<div class="panel-heading" ng-click="plinefunc(pline.productline_name)">
<h6>
<div class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" ng-href="{{productline_name}}">{{pline.productline_name}}</div>
</h6>
</div>
<div id="{{productline_name}}" class="panel-collapse collapse">
<div class="panel-body">
<ul>
<li class="panel-title" ng-repeat="prd in detp"><a ng-click="cfilter(prd.product_name)"><h5>{{prd.product_name}}</h5></a></li>
</ul>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
Can any one help in this? what is the correct syntax to use to link panel heading and panel body via binding expresion?
Note: I am using binding expression for linking only to avoid opening all other sub panel heading contents on-clicking one of the sub panel heading.

How to make Accordion Panel-title clickable area bigger

I am trying to make the entire panel-heading click-able. I tried wrapping the div with some css.
plunkr
#box {
padding: 10px;
display: block;
width: 100%;
}
HTML:
<a id="box">
<div class="panel-heading" toggle target="collapse{{$index}}">
<h4 class="panel-title">
<span style="font-size:12px">Name :</span> <span ng-click="selectJob(currentItem, $index)">{{currentItem.JobName}}</span>
</h4>
</div>
</a>
Move ngClick to a element:
<a id="box" ng-click="selectEmployee(employee, $index)">
<div class="panel-heading" toggle target="collapse{{$index}}">
<h4 class="panel-title">
<span>{{employee.firstName}} {{employee.lastName}}</span>
</h4>
</div>
</a>
Demo: http://plnkr.co/edit/nOGHHQWxT5lEKbulmGtJ?p=preview

Angularjs ui.bootstrap Accordion

I found this accordion effect which works very nicely: http://angular-ui.github.io/bootstrap/
But I need the accordion to open differently, so that the content of each accordion-group appears above the accordion-header that opens it. Just wondering if anyone knows a simple way to accomplish this or if I'll have to make my own custom accordion.
The UIBootstrap accordion does not support having the panel content above the title by default.
Below is the accordion-group.html template, which is the HTML for each panel. As you can see there is currently no logic to cover your use case.
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a class="accordion-toggle" ng-click="toggleOpen()" accordion-transclude="heading"><span ng-class="{'text-muted': isDisabled}">{{heading}}</span></a>
</h4>
</div>
<div class="panel-collapse" collapse="!isOpen">
<div class="panel-body" ng-transclude></div>
</div>
</div>
https://github.com/angular-ui/bootstrap/blob/master/template/accordion/accordion-group.html
However, it should be fairly simply to modify this file to have the title below the content. Simply change this template to have the divs in the order you prefer.
<div class="panel panel-default">
<div class="panel-collapse" collapse="!isOpen">
<div class="panel-body" ng-transclude></div>
</div>
<div class="panel-heading">
<h4 class="panel-title">
<a class="accordion-toggle" ng-click="toggleOpen()" accordion-transclude="heading"><span ng-class="{'text-muted': isDisabled}">{{heading}}</span></a>
</h4>
</div>
</div>
I would suggest taking a fork of the repository on GitHub, so you can make your changes without losing the benefits of version control. http://github.com/angular-ui/bootstrap

Toggling accordion panel icons with ng-class and ng-click

I have an accordion with "chevron" icons that are toggled to point up or down when clicked, this is done with ng-click and ng-class. The accordion only permits one panel to be open at the same time - so when I click on a panel that is closed, the panel that is open closes. But how do I toggle the chevron icon on the open panel that is getting closed with ng-click?
Originally i could do it with DOM manipulation etc, but since this is a partial view in angular I cannot do it.
Code:
<div class="panel-group" id="accordion">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" ng-click="firstpaneisopen=!firstpaneisopen">
<i class="glyphicon" ng-class="{'glyphicon-chevron-up': firstpaneisopen, 'glyphicon-chevron-down': !firstpaneisopen}"></i> Collapsible Group Item #1
</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse in">
<div class="panel-body">
Body
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" ng-click="secondpaneisopen=!secondpaneisopen>
<i class="glyphicon" ng-class="{'glyphicon-chevron-up': secondpaneisopen, 'glyphicon-chevron-down': !secondpaneisopen}"></i> Collapsible Group Item #2
</a>
</h4>
</div>
<div id="collapseTwo" class="panel-collapse collapse">
<div class="panel-body">
Body
</div>
</div>
</div>
</div>
This is what I've tried and it seems to work
In my controller I have
$scope.menuStatus = [ { isOpen : true },
{ isOpen : false },
{ isOpen : false } ]
In my html I have
<accordion id='cntLeftMenu' close-others='false'>
<accordion-group is-open='menuStatus[0].isOpen'>
<accordion-heading class='menu-title'>
Cars <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': menuStatus[0].isOpen , 'glyphicon-chevron-right': !menuStatus[0].isOpen }"></i>
</accordion-heading>
<ul class='left-menu'>
<li><a href=''>test1</a></li>
<li><a href=''>test1</a></li>
<li><a href=''>test1</a></li>
</ul>
</accordion-group>
<accordion-group is-open='menuStatus[1].isOpen'>
<accordion-heading class='menu-title'>
Customers <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': menuStatus[1].isOpen , 'glyphicon-chevron-right': !menuStatus[1].isOpen }"></i>
</accordion-heading>
<ul class='left-menu'>
<li><a href=''>test1</a></li>
<li><a href=''>test1</a></li>
<li><a href=''>test1</a></li>
</ul>
</accordion-group>
<accordion-group is-open='menuStatus[2].isOpen'>
<accordion-heading class='menu-title'>
Staff <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': menuStatus[2].isOpen , 'glyphicon-chevron-right': !menuStatus[2].isOpen }"></i>
</accordion-heading>
<ul class='left-menu'>
<li><a href=''>test1</a></li>
<li><a href=''>test1</a></li>
<li><a href=''>test1</a></li>
</ul>
</accordion-group>
<accordion>
How about working with CSS? Bootstrap adds a class collapsed on the html element that has the data-toggle="collapse". When the slide opens, it removes this collapsed class. We can then work with css to, for example, rotate the span element (a child of the element that has the data-toggle attribute).
<style>
button.collapsed span {
transform: rotate(-90deg);
}
</style>
<button type="button" class="btn btn-info collapsed" data-toggle="collapse" data-target="#demo">
Simple collapsible
<span class="glyphicon glyphicon-chevron-down"></span>
</button>
<div id="demo" class="collapse">
Lorem ipsum dolor...
</div>
IMPORTANT NOTE : Ensure collapsed class is added to the element that has the data-toggle="collapse" attribute for this to work smoothly. Otherwise, on initial loading of the element, the span element doesn't rotate as expected the first time.
I would recommend that you check out 'UI Bootstrap' from the AngularUI team. It's a collection of "Bootstrap components written in pure AngularJS".
http://angular-ui.github.io/bootstrap/
Their website features an example which shows their Accordion directive using ng-class to toggle the chevron icons.
http://angular-ui.github.io/bootstrap/#/accordion
Their directive also features a close-others attribute which, if true, will ensure only a single panel is open at any one time.
<accordion close-others="true">
The easiest solution I have ever think. And not to use any controller,
<div
class="fa fa-fw list-arrow"
ng-class="{'fa-angle-down': isClicked, 'fa-angle-right' : !isClicked}"
ng-click="isClicked = !isClicked">
</div>
You can write similar like me.
Did some researching, I was able to use this method to add the class open to the panel-header when it's toggled open. This is example allows multiple panels to be open and uses Angular Strap Collapse.
Template:
<div class="panel-group"
role="tablist"
data-ng-model="multiplePanels.activePanels"
data-allow-multiple="true"
data-bs-collapse>
<div class="panel panel-default" ng-repeat="location in locations">
<div class="panel-heading"
role="tab"
data-ng-class="{'open' : multiplePanels.activePanels.indexOf($index) > -1}"
bs-collapse-toggle>
<h3>Some Header Stuff</h3>
</div>
<div class="panel-collapse" role="tabpanel" bs-collapse-target>
<div class="panel-body">
<p>Stuff in the panel body...</p>
</div>
</div>
</div>
</div>
JS in the controller:
$scope.multiplePanels.activePanels = [];
You can use bootstrap (tested in 4+) collapse and the following styles to toggle the button;
<style>
[id^='particon'] {
display: block !important;
}
[id^='particon']:after {
font-family: 'Glyphicons Halflings';
color: grey;
}
[id^='particon'].collapse:after {
content: "\e081";
}
[id^='particon'].collapse.show:after {
content: "\e082";
}
/*optional*/
[id^='particon'].collapsing {
transition: none;
}
</style>
For fully working snipplet;
https://js.do/code/changecollapseicon
After some research i've got one way to solve this.
JS:
$scope.firstpaneisopen = false;
$scope.secondpaneisopen = false;
Modified ng-click on the first pane:
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" ng-click="firstpaneisopen=!firstpaneisopen; secondpaneisopen=false">
vice versa on the second pane.
I don't think this is any elegant solution, especially if we got more than two panes, but it works.

Resources