Please disable your adblock and script blockers to view this page

Search this blog

Thursday, 16 April 2015

Build selectOneChoice to show hierarchical (tree style) data programmatically in ADF

This post is based on an old article from Frank Nimphius How - to build a select one choice displaying hierarchical selection data

This article is about showing tree structure data in af:selectOneChoice component using ADF BC , it makes use of tree binding and af:forEach
Same concept i have used to populate data from managed bean using List data structure

Let's see the implementation part - how to populate tree style selectOneChoice programatically ?

First we have to design a Java Bean class in such a way that it can hold  master -detail type of data

A class that represents a List for Parent Values
                          ======> A list of same type to hold Child Values

See bean class code-

import java.util.ArrayList;
import java.util.List;

public class Seasons {
    public Seasons(String name) {
        this.name = name; // To Store Header Values (Storing Seasons Name :))
    }
    // Season and Charater Name
    private String name;
    // To Store Detail Values (Storing Season's Charatcers)
    private List<Seasons> characters = new <Seasons>ArrayList();

    public void setCharacters(List<Seasons> empDet) {
        this.characters = empDet;
    }

    public List<Seasons> getCharacters() {
        return characters;
    }


    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
    // This methods directly add characters value in list
    public void addCharaters(Seasons employee) {
        characters.add(employee);
    }
}

Now how to use this bean in managed bean to add records, i have written code in constructor to populate values on class load




    // Master List to populate data in selectOnce choice
    List<Seasons> seasonList = new ArrayList<Seasons>();

    public void setSeasonList(List<Seasons> seasonList) {
        this.seasonList = seasonList;
    }

    public List<Seasons> getSeasonList() {
        return seasonList;
    }
    //Constructor of Managed Bean to populate data on page load (you can move this code )
    public TreeStyleLovBean() {
        super();
        // Creating tree for Seasons and Characters details
        // Adding Master Values (seasons)
        Seasons season1 = new Seasons("Game of Thrones");

        // Adding Detail Values (Child Node-Characters)
        Seasons character = new Seasons("Tywin Lannister");
        season1.addCharaters(character);
        character = new Seasons("Tyrion Lannister");
        season1.addCharaters(character);
        character = new Seasons("Jaime Lannister");
        season1.addCharaters(character);
        character = new Seasons("Cersie Lannister");
        season1.addCharaters(character);
        character = new Seasons("Ned Stark");
        season1.addCharaters(character);

        // Adding Master Values (seasons)
        Seasons season2 = new Seasons("Arrow");

        // Adding Detail Values (Child Node-Characters)
        character = new Seasons("Oliver Queen");
        season2.addCharaters(character);
        character = new Seasons("Moira Queen");
        season2.addCharaters(character);
        character = new Seasons("Laurel Lance");
        season2.addCharaters(character);
        character = new Seasons("Sara Lance");
        season2.addCharaters(character);

        // Adding Master Values (seasons)
        Seasons season3 = new Seasons("Vikings");

        // Adding Detail Values (Child Node-Characters)
        character = new Seasons("Ragnar Lothrak");
        season3.addCharaters(character);

        // Adding Master Values (seasons)
        Seasons season4 = new Seasons("The Flash");

        // Adding Detail Values (Child Node-Characters)
        character = new Seasons("Barry Allen");
        season4.addCharaters(character);
        character = new Seasons("Harisson Wells");
        season4.addCharaters(character);
        character = new Seasons("Iris West");
        season4.addCharaters(character);
        character = new Seasons("Joe");
        season4.addCharaters(character);

        // Adding all list to topList
        seasonList.add(season1);
        seasonList.add(season2);
        seasonList.add(season3);
        seasonList.add(season4);

    }
how to bind this managed bean to selectOneChoice ? i have used same concept as described in Frank's article using af:forEach


<af:selectOneChoice id="selectBox" label="Choose Character" valuePassThru="true"
                                        styleClass="employeeSelectBox" contentStyle="width:150px;"
                                        binding="#{viewScope.TreeStyleLovBean.selectOneValueBind}">
                        <af:forEach items="#{viewScope.TreeStyleLovBean.seasonList}" var="seasonNm">
                            <af:selectItem label="#{seasonNm.name}" disabled="true" id="si1"/>
                            <af:forEach items="#{seasonNm.characters}" var="characterNm">
                                <af:selectItem label="#{characterNm.name}" value="#{characterNm.name}" id="si2"/>
                            </af:forEach>
                        </af:forEach>
                    </af:selectOneChoice>

you can see here that first forEach is populated from master list and iterates over list of seasons and first selectItem show season's name
the inner forEach makes used of character list that is defined in Java Bean class and stores season wise character's name
Rest is same - a CSS is used to differentiate color and alignment of parent and child records (same as Frank's article)


<f:facet name="metaContainer">
                <af:group>
                    <![CDATA[
<style>
.employeeSelectBox option{text-indent:15px;color:darkgreen;}
.employeeSelectBox option[disabled]{color:red; background-color:#dddddd; 
font-weight: bold; text-indent:0px}
</style>
]]>
                </af:group>
            </f:facet>

Now run this application - see how it appears on page



It looks quite good :) to get selected value in bean just use componentBinding.getValue();

Sample ADF Application-Download (Jdev 12.1.3)
Cheers , Happy Learning 

Tuesday, 7 April 2015

Better UI -Show jQuery notification message (for error, warning, info) in Oracle ADF

Hello all,
Another post about using jQuery with ADF Faces , this post is about showing a notification message using jQuery in your ADF Application
Normally we use default FacesMesage to show error, warning and info messages in ADF

here i am using jQuery growl library , you can download files from Growl : jQuery Informative Messages Plugin

Let's see how to integrate this library with ADF Faces, you will get two files from above link
one is JavaScript file (jQuery script) and other one is CSS file (style-sheet for notification UI)



Add both files to viewController project under Web Content

now add reference of both files (JS and CSS) in page and also jQuery library to execute growl script


 <af:resource source="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js" type="javascript"/>
            <af:resource source="js/jquery.growl.js" type="javascript"/>
            <af:resource source="style/jquery.growl.css" type="css"/>

Now i have added 3 buttons on page to show different messages on button click and created a managed bean to define action for each button
On button click i have called jQuery script to invoke notification message
see managed bean code-


import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.apache.myfaces.trinidad.render.ExtendedRenderKitService;
import org.apache.myfaces.trinidad.util.Service;

public class ShowJqNotification {
    public ShowJqNotification() {
    }

    /**Helper method to execute javascript
     * @param script
     */
    public void calljqHelper(String script) {
        FacesContext context = FacesContext.getCurrentInstance();
        ExtendedRenderKitService erks = Service.getService(context.getRenderKit(), ExtendedRenderKitService.class);
        erks.addScript(context, script);
    }
    //Change your message as per requirement 
    /**Method to invoke Error Message
     * @param actionEvent
     */
    public void showErrMessageAction(ActionEvent actionEvent) {
        calljqHelper("$.growl.error({ message: \"Hi this is error message!\" });");

    }

    /**Method to invoke Warnign Message
     * @param actionEvent
     */
    public void showWarningMessageAction(ActionEvent actionEvent) {
        calljqHelper("$.growl.warning({ message: \"Hi this is Warning!\" });");
    }

    /**Method to invoke Info Message
     * @param actionEvent
     */
    public void showNoticeMessageAction(ActionEvent actionEvent) {
        calljqHelper("$.growl.notice({ message: \"Hi this is Notice!\" });");
    }

}

All done, now run application and check - how it looks :)


this is default look of script , you can customize it , just change some parameters in both JS and CSS files
I have changed some parameters in both files and see how it looks now

Cheers, Happy Learning :)
Sample ADF Application- Download

Read more about - Jquery and ADF Working together

Image zoom (power zoomer) effect using Jquery in ADF Faces
Show animated Image Caption using jQuery in ADF Faces
Using JQuery in Oracle ADF

Friday, 3 April 2015

Stretch ADF Faces Components to fit browser width (Show as row-column layout- inline block )

Recently i have seen a thread in OTN about layout of components (How to use components to show a particular layout)
ADF layout for showing email recipients

Requirement was simple, user want to show components up to maximum available width (browser window width) first and then move to next line and show other components
So i thought to document it here :)

Suppose i have to show 6 images on page (horizontally) , so for that i have used 6 group layout
one for each image and button



See xml source-

<af:panelGroupLayout id="pgl1" layout="horizontal">
                    <af:panelGroupLayout id="pgl2" layout="vertical" halign="center"
                                         inlineStyle="padding:2px;">
                        <af:image source="#{resource['images:a_hobbit_house-wallpaper-1280x800.jpg']}"
                                  shortDesc="Hobbit House" id="i1" inlineStyle="width:250px;height:200px; "/>
                        <af:button text="View" id="b1"/>
                    </af:panelGroupLayout>
                    <af:panelGroupLayout id="pgl3" layout="vertical" halign="center"
                                         inlineStyle="padding:2px;">
                        <af:image source="#{resource['images:beach_at_sunset_3-wallpaper-1440x900.jpg']}"
                                  shortDesc="Sunset at Beach" id="i2" inlineStyle="width:250px;height:200px; "/>
                        <af:button text="View" id="b2"/>
                    </af:panelGroupLayout>
                    <af:panelGroupLayout id="pgl4" layout="vertical" halign="center" inlineStyle="padding:2px;">
                        <af:image source="#{resource['images:icelands_ring_road-wide.jpg']}" shortDesc="Ring Road"
                                  id="i3" inlineStyle="width:250px;height:200px; "/>
                        <af:button text="View" id="b3"/>
                    </af:panelGroupLayout>
                    <af:panelGroupLayout id="pgl5" layout="vertical" halign="center" inlineStyle="padding:2px;">
                        <af:image source="#{resource['images:road_to_mount_cook-wallpaper-1280x800.jpg']}"
                                  shortDesc="Road To Mount Cook" id="i4" inlineStyle="width:250px;height:200px; "/>
                        <af:button text="View" id="b4"/>
                    </af:panelGroupLayout>
                    <af:panelGroupLayout id="pgl6" layout="vertical" halign="center" inlineStyle="padding:2px;">
                        <af:image source="#{resource['images:skyscrapers_reflections-wallpaper-1280x800.jpg']}"
                                  shortDesc="Skycrappers " id="i5" inlineStyle="width:250px;height:200px; "/>
                        <af:button text="View" id="b5"/>
                    </af:panelGroupLayout>
                    <af:panelGroupLayout id="pgl7" layout="vertical" halign="center" inlineStyle="padding:2px;">
                        <af:image source="#{resource['images:tufandisli_1387241118_57.jpg']}" shortDesc="Tufan"
                                  id="i6" inlineStyle="width:250px;height:200px; "/>
                        <af:button text="View" id="b6"/>
                    </af:panelGroupLayout>
                </af:panelGroupLayout>

 and how it looks on page-


You can see here last image is not appearing properly because total width of all images has crossed maximum available width of browser window
Now i want to show last image on next line
So to do this set parent panel group layout to default layout and set display:inline-block for all child panel group layout


<af:panelGroupLayout id="pgl1">
                    <af:panelGroupLayout id="pgl2" layout="vertical" halign="center"
                                         inlineStyle="padding:2px;display:inline-block;">
                        <af:image source="#{resource['images:a_hobbit_house-wallpaper-1280x800.jpg']}"
                                  shortDesc="Hobbit House" id="i1" inlineStyle="width:250px;height:200px; "/>
                        <af:button text="View" id="b1"/>
                    </af:panelGroupLayout>
                    <af:panelGroupLayout id="pgl3" layout="vertical" halign="center"
                                         inlineStyle="padding:2px;display:inline-block;">
                        <af:image source="#{resource['images:beach_at_sunset_3-wallpaper-1440x900.jpg']}"
                                  shortDesc="Sunset at Beach" id="i2" inlineStyle="width:250px;height:200px; "/>
                        <af:button text="View" id="b2"/>
                    </af:panelGroupLayout>
                    <af:panelGroupLayout id="pgl4" layout="vertical" halign="center"
                                         inlineStyle="padding:2px;display:inline-block;">
                        <af:image source="#{resource['images:icelands_ring_road-wide.jpg']}" shortDesc="Ring Road"
                                  id="i3" inlineStyle="width:250px;height:200px; "/>
                        <af:button text="View" id="b3"/>
                    </af:panelGroupLayout>
                    <af:panelGroupLayout id="pgl5" layout="vertical" halign="center"
                                         inlineStyle="padding:2px;display:inline-block;">
                        <af:image source="#{resource['images:road_to_mount_cook-wallpaper-1280x800.jpg']}"
                                  shortDesc="Road To Mount Cook" id="i4" inlineStyle="width:250px;height:200px; "/>
                        <af:button text="View" id="b4"/>
                    </af:panelGroupLayout>
                    <af:panelGroupLayout id="pgl6" layout="vertical" halign="center"
                                         inlineStyle="padding:2px;display:inline-block;">
                        <af:image source="#{resource['images:skyscrapers_reflections-wallpaper-1280x800.jpg']}"
                                  shortDesc="Skycrappers " id="i5" inlineStyle="width:250px;height:200px; "/>
                        <af:button text="View" id="b5"/>
                    </af:panelGroupLayout>
                    <af:panelGroupLayout id="pgl7" layout="vertical" halign="center"
                                         inlineStyle="padding:2px;display:inline-block;">
                        <af:image source="#{resource['images:tufandisli_1387241118_57.jpg']}" shortDesc="Tufan"
                                  id="i6" inlineStyle="width:250px;height:200px; "/>
                        <af:button text="View" id="b6"/>
                    </af:panelGroupLayout>
                </af:panelGroupLayout>

Now it appears like this -

now again test it by increasing and decreasing browser window width , images and group layout are adjusted as per screen size automatically like a grid view (row and columns)

Thanks , Happy Learning :)
Sample ADF Application- Download