Saturday, June 4, 2016

ADF: Colorful Panel Accordion (ShowDetail Item headers)

Problem Description: In ADF we can mostly change styles of all components. Recently in one of forum post it was asked to do styling of ADF panel accordion to have different colors of header. Like below



Problem here is if I style panel-accordion provides a way to style its header. But that style will be applied to all headers. So I can have yellow headers but all will become yellow. How can we have different headers with different colors.

Solution: Lets go from simple to complex

What if we just need to make all headers yellow

<af:panelAccordion id="pa1" >
          <af:showDetailItem text="showDetailItem 1" id="sdi1"/>
          <af:showDetailItem text="showDetailItem 2" id="sdi2"/>
          <af:showDetailItem text="showDetailItem 3" id="sdi3"/>
          <af:showDetailItem text="showDetailItem 4" id="sdi4"/>
  </af:panelAccordion>

af|panelAccordion::header{
  background: yellow none no-repeat fixed center !important; 
}

af|panelAccordion::header-subsequent{
  background: yellow none no-repeat fixed center !important; 
}

af|panelAccordion::header-disclose {
  background: yellow none no-repeat fixed center !important; 
}


Above settings will impact all panel accordions. What if we want it for only specific panel accordion
We can add a class with panelAccordion and refer that in css

<af:panelAccordion id="pa1" styleClass="colorfulAccordian">
          <af:showDetailItem text="showDetailItem 1" id="sdi1"/>
          <af:showDetailItem text="showDetailItem 2" id="sdi2"/>
          <af:showDetailItem text="showDetailItem 3" id="sdi3"/>
          <af:showDetailItem text="showDetailItem 4" id="sdi4"/>
        </af:panelAccordion>

.colorfulAccordian af|panelAccordion::header{
  background: yellow none no-repeat fixed center !important; 
}

.colorfulAccordian af|panelAccordion::header-subsequent{
  background: yellow none no-repeat fixed center !important; 
}

.colorfulAccordian af|panelAccordion::header-disclose {
  background: yellow none no-repeat fixed center !important; 
}


Till here everything is great and Oracle provides selectors to style accordion headers. Now what if we want to style each accordion header differently.

There is no direct way to apply different different styles for each panel accordion headers. They are governed by one style only af|panelAccordion::header (or header-susequent/header-disclose). Any change in this style will affect all headers equally.

To style individual headers we need to use css styling in combination of adf selectors. We need to use nth child selector of css to select one particular header (h1) tag.


.colorfulAccordian af|panelAccordion::header{
  background: #000000 none no-repeat fixed center !important;
}


.colorfulAccordian af|panelAccordion::header-subsequent{
  background: #000000 none no-repeat fixed center !important;
}

.colorfulAccordian.af|panelAccordion h1:nth-child(2) {
  background-color: yellow !important;
}

.colorfulAccordian.af|panelAccordion h1:nth-child(4), af|panelAccordion h1:nth-child(5){
  background-color: red !important;

}
.colorfulAccordian.af|panelAccordion h1:nth-child(6), af|panelAccordion h1:nth-child(7){
  background-color: green !important;

}

.colorfulAccordian.af|panelAccordion h1:nth-child(8), af|panelAccordion h1:nth-child(9){
  background-color: blue !important;


}

Above styles will give you required output. 
Similarly if you want to style only one tab heading of a panelTab



<af:panelTabbed id="pt1" styleClass="colorfulTab">
          <af:showDetailItem text="showDetailItem 5" id="sdi5"/>
          <af:showDetailItem text="showDetailItem 6" id="sdi6"/>
        </af:panelTabbed>

and you want to style only first tab


.colorfulTab.af|panelTabbed af|panelTabbed::viewable-tabs > div:nth-child(1) af|panelTabbed::tab-text-link {
  color: yellow !important;
}


To style only second tab

.colorfulTab.af|panelTabbed af|panelTabbed::viewable-tabs > div:nth-child(2) af|panelTabbed::tab-text-link {
  color: yellow !important;
}


We have to use nth-child selector of css because Oracle by default style all panelAccordion headers (or panelTab's tab) with one single style. There is no way to provide different styles for different headers. Ideally I would have loved to have an attribute in panelAccordion like headerStyle, which I can set as comma separated classnames. Then framework could have taken care to apply those class on individual headers. I just need to provide styles on those classes.


Disclaimer: This solution is not upgrade safe as there is no guarantee that header tags (h1) will be placed same way in html hierarchy as it is today. If ADF framework changes h1 tag in html then whole implementation will fail and you may need to write a new class.