JDeveloper 11g will gives us wonderful charts. Colorful, powerful, exhilerating etc. But since it is not yet production, I might just write this little story about yet another way of creating a Bar Chart. In this article, I will show you how using simple InputText elements and little CSS fiddling, we can easily create a simple Bar Chart, that looks not all bad. Like many of my articles, it is more to entertain than to educate.
My objective, for whatever reason, is to create a bar chart in my ADF Faces application that looks like this:
What you see here is an overview of all employees in the EMP table in the SCOTT schema and their salaries. This is implemented using:
- two read-only inputText elements
- an af:iterator element
- a managed bean with color definitions
- a managed for some simple calculations
- a little CSS styling on one of the inputText elements
I started out by creating a new ADF application – JSF/ADF BC – and a straightword ADF BC ApplicationModule with just a single default Entity and View Object for the EMP table in the SCOTT schema. Next I created a new JSF page. I dragged the EmpView1 collection to the page, dropping it as a table – the laziest way to create the iterator.
Then I created the following JSF fragment:
<af:iterator varStatus="status" var="emp"
value="#{bindings.EmpView1.collectionModel}">
<af:inputText value="#{emp.Ename}" />
<af:inputText value="#{emp.Sal}"/>
</af:iterator>
This iterates over the EMP records and writes the Ename and Salary for each one of them. At this point, I can delete the af:table from the page, as it has served its purpose.
At this point it would be nice to add a little color. We can easily do so using CSS, through the Inline Style property on the InputText element:
<af:inputText value="#{emp.Sal}"
inlineStyle="background-color:red"/>
This makes all fields that display the salary red. Not pretty. I want to use various colors. So I created a managed bean that specifies a range of colors:
<managed-bean>
<managed-bean-name>colors</managed-bean-name>
<managed-bean-class>java.util.HashMap</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<map-entries>
<key-class>java.lang.Integer</key-class>
<map-entry>
<key>0</key>
<value>red</value>
</map-entry>
<map-entry>
<key>1</key>
<value>purple</value>
</map-entry>
<map-entry>
<key>2</key>
<value>yellow</value>
</map-entry>
<map-entry>
<key>3</key>
<value>blue</value>
</map-entry>
... and so on
</map-entries>
</managed-bean>
Now I can refer to the colors in the managed bean in the following way:
<af:inputText disabled="true"
value="#{emp.Sal}"
inlineStyle="background-color:#{colors[status.index]}"/>
Note that I use the status.index EL parameter that was defined in the af:iterator earlier on. This gives me a new color for every employee, at least for as many colors as I have defined in the managed bean. However, if the number of employees exceeds the number of colors, I want to start again with the first color. Using the Calculator bean – a bean I have discussed previously on this weblog – I can use the MOD(ULO) operation to start again after 8 colors, as that is the number specified in the Managed Bean colors:
<af:inputText disabled="true"
value="#{emp.Sal}"
inlineStyle="background-color:#{colors[Calculator.RESET[status.index][8].MOD.INTEGER.EQUALS]}"/>
I have certainly make progress. However, the most important part of the Bar Chart functionality – bars with lengths proportional to the value they represent – is not yet there. However, with everything we have in place, it is very simple: we use the columns property of the inputText element to have bars of varying lengths:
<af:inputText disabled="true"
columns="#{Calculator.RESET[emp.Sal][6000].DIVIDE[60].MULTIPLY.LONG.EQUALS}"
value="#{emp.Sal}"
inlineStyle="background-color:#{colors[Calculator.RESET[status.index][8].MOD.INTEGER.EQUALS]}"/>
I have used 6000 as the reference value – all salaries are smaller than that value. The length of each bar – the value of property columns – is calculated as 60 (the maximum length) times the Salary value divided by 6000 (the reference Salary). The complete JSF fragment now looks like this:
<af:panelHeader text="Employees' Salary BarChart"/>
<af:iterator varStatus="status" var="emp"
value="#{bindings.EmpView1.collectionModel}">
<h:panelGrid columns="2">
<af:inputText value="#{emp.Ename}" disabled="true" columns="11"
inlineStyle="background-color:rgb(255,255,255); border-color:rgb(255,255,255); border-style:none; color:rgb(0,0,0);"/>
<af:inputText disabled="true"
columns="#{Calculator.RESET[emp.Sal][6000].DIVIDE[60].MULTIPLY.LONG.EQUALS}"
value="#{emp.Sal}"
inlineStyle="background-color:#{colors[Calculator.RESET[status.index][8].MOD.INTEGER.EQUALS]}"/>
</h:panelGrid>
</af:iterator>
And that is all that is required to create such a happy bar chart.
Resources
Download the JDeveloper 10.1.3.2 Application: ADFTableAsBarChart.zip (and add the JSF and ADF Faces jars to the WEB-INF\lib directory yourself).
Hi,
just two quick notes: if you don’t want to have input fields, then you can also use objectImage components with fixed height and varying width properties to achieve something similar.
Plus you can also make vertical bars by using objectImage components with fixed width and varying height properties, e.g. in a rowLayout.
Regards,
Patrik