GuillaumeA
GuillaumeA

Reputation: 3545

How to set class/style of accordion heading in Angular UI

I'm using Angular UI to render littel database entries in an accordion. In a first trial, I used bootstrap, but as I integrated AngularJS views, accordion is no more fully working (empty href...). I then replaced my bootstrap accordion with angular UI bootstrap one and the default template.

My problem is that in the bootstrap version, I managed to stylized the heading depending on the accordion title (I was using the ng-repeat directive, and the ng-style inside the heading). I tried to do the same with Angular UI, but even my custom class is not rendered.

This sample code was working great with bootstrap, but no more with ui.boostrap accordion :

accordion-group.accordion-groupLog(ng-repeat="item in data.entries | filter:search") 
   accordion-heading.accordion-headingLog(ng-style="{backgroundColor: styles[item.importance-1].bkcolor, color: styles[item.importance-1].color}")
         {{item.title}}   ({{item.importance}})

The goal here is to apply a different style (background color and text color) based on an item field. Furthermore, the class accordion-headingLog is to resize the accordion default size.

Here is the rendered code :

<div class="accordion-groupLog accordion-group ng-scope" ng-repeat="item in data.entries | filter:search">
   <div class="accordion-heading">
      <a class="accordion-toggle ng-binding" ng-click="isOpen = !isOpen" accordion-transclude="heading">
......

And I was expecting something like :

<div class="accordion-groupLog accordion-group ng-scope" ng-repeat="item in data.entries | filter:search">
   <div ng-style="{backgroundColor: styles[item.importance-1].bkcolor}" class="accordion-heading accordion-headingLog" style="background-color: rgb(214, 24, 40);">

[EDIT] I tried to put the accordion-headingLog class with ng-class attribute, but it does not work either. Just to test, I tried to apply the class and the style inside the body of the accordion, and it works well. I conclue that the accordionHeading directive does not accept any class or attribute ? How to dynamically apply a style on the heading then ???

[EDIT] Another trial was to build my own template. I am able to apply the accordion-headingLog class to the heading, but how can I set a customizable style ? I tried to use ng-style and apply a fixed style, but it does not work.

script(type="text/ng-template", id="template/accordion/accordion-group.html").
    div.accordion-group
    div.accordion-heading.accordion-headingLog(ng-style="{background-color: #123456")
       a.accordion-toggle(ng-click="isOpen = !isOpen", accordion-transclude="heading") {{heading}}
    div.accordion-body(collapse="!isOpen")
       div.accordion-inner(ng-transclude)

Upvotes: 9

Views: 32580

Answers (3)

Shbenzer
Shbenzer

Reputation: 51

Just dealt with this issue after upgrading to most recent versions of angular, bootstrap, etc. and none of these related answers fully answer this question imo.

My experience is that there's really two main ways to do it

  1. using the [panelClass] attribute and then supplanting the existing styling in the accordion component and its children.

This way is more finicky and will likely take a lot more trial and error to configure to your desired specs.

html:

<accordion>
    <accordion-group heading="test" [panelClass]="'custom-class'"></accordion-group>
    <accordion-group heading="test2" [panelClass]="'custom-class'"></accordion-group>
</accordion>

note the extra set of quotation marks in the [panelClass] - Angular looks for presets otherwise. You can get around this by initializing a string variable that contains the name of the custom class you desire and popping that in there, instead.

possible css (might not be precise):

accordion-group::ng-deep .custom-class>a{background-color: black !important;}
accordion-group::ng-deep .custom-class>a:hover{color:white !important;}
  1. Track down the specific classes the components utilize (your web browser's developer tools are useful) and use the usual css specs (::ng-deep, !important, '>', etc.), as necessary. In the accordion-group, for example, the headings for each group utilize .btn, .btn-link, etc.

E.g., if you wanted to change the default underlines in an accordion-group's heading to only display on the (hover) event:

html:

<accordion>
    <accordion-group heading="test" id="blah"></accordion-group>
    <accordion-group heading="test2"></accordion-group>
</accordion>

css:

#blah .btn{text-decoration: none;}
#blah .btn:hover{text-decoration: underline;}

I find method #2 to be simpler, it just requires a little investigation into the components you use (probably not a bad thing anyway).

Upvotes: 0

nipo
nipo

Reputation: 180

I had the same problem, the fast solution for me was change the CSS and add a class into the parent "accordion-group":

Template:

<accordion close-others="true">
    <accordion-group ng-repeat="elem in group.elements" is-open="isopen" ng-class="{'collapsed': !isopen}">
        <accordion-heading ng-click="isopen=!isopen">
            {{ elem.name }} 
        </accordion-heading>
        This content is straight in the template.
    </accordion-group>
</accordion>

HTML:

<accordion close-others="true">
    <div class="panel-group" ng-transclude="">
        <!-- ngRepeat: elem in group.elements -->
        <div class="panel panel-default ng-isolate-scope collapsed" ng-repeat="elem in group.elements" is-open="isopen" ng-class="{'collapsed': !isopen}">
            <div class="panel-heading">
                <h4 class="panel-title">
                <a href="" class="accordion-toggle" ng-click="toggleOpen()" accordion-transclude="heading">
                    <span class="ng-binding ng-scope"> 2001 </span></a>
                </h4>
            </div>
            <div class="panel-collapse collapse" collapse="!isOpen" style="height: 0px;">
                <div class="panel-body" ng-transclude="">
                    <accordion-heading ng-click="isopen=!isopen" class="ng-scope"></accordion-heading>
                    <span class="ng-scope">
                        This content is straight in the template.
                    </span>
                </div>
            </div>
        </div>
    </div>
</accordion>

CSS:

accordion>.panel-group .panel.collapsed .panel-heading .accordion-toggle {
    color: #478fca;
    font-weight: 400;
    background-color: #F9F9F9;
}

You can create a directive to change the class of children as well, but I do not believe that is the best solution.

Upvotes: 2

TyndieRock
TyndieRock

Reputation: 996

Angular-UI's accordion has an accordionHeading directive that allows you to include HTML. The example in the source code:

// Use accordion-heading below an accordion-group to provide a heading containing HTML
// <accordion-group>
//   <accordion-heading>Heading containing HTML - <img src="..."></accordion-heading>
// </accordion-group>

So maybe you can do something like this to conditionally apply your custom css:

<accordion-group>
<accordion-heading ng-class="{'custom-style': item.title }"> Your Title </accordion-heading>
</accordion-group>

Here is the Angular-UI Accordion source code https://github.com/angular-ui/bootstrap/blob/master/src/accordion/accordion.js

Upvotes: 8

Related Questions