Please disable your adblock and script blockers to view this page

Search this blog

Monday, 5 August 2013

Creating dynamic layout (form and UI Component) using ADF Faces

hello all,
today i had a scenario to create UI Components at run time and i tried to do that on my ADF page.
searched lot in Google and finally all summary is in post.

Suppose you have to create UI Components (input text, buttons, check-boxes etc ) or form (set of multiple UI Components) at runtime - follow these steps

  • Find a parent component to create child under it as any layout (panel form, panel group, af:form etc)
  • Suppose you have a page with a panel form layout, now you have to create child components in this form layout at runtime
  • Bind this form layout to managed bean

  • <af:panelFormLayout id="pfl1" rows="2" binding="#{DynamicCompBean.panelFormLay}"/>
    

  • Now thanks to Mahmoud A. Elsayed for this method, that adds child component to parent component

  •     public void addComponent(UIComponent parentUIComponent, UIComponent childUIComponent) {
            parentUIComponent.getChildren().add(childUIComponent);
            AdfFacesContext.getCurrentInstance().addPartialTarget(parentUIComponent);
        }
    

  • you can call this method , wherever you want to create UI Component and add it to page .



  • Now i have created a button on page and a radio box to select which component should be created
  • Now on button click , i have generated components conditionally based on selection
  • To generate any component - see managed bean code to create input text

  •             RichInputText ui = new RichInputText();
                ui.setId("rit1");
                ui.setLabel("Input text");
                ui.setValue("Hello ADF");
                ui.setContentStyle("font-weight:bold;color:red");
    

  • same as this ,for other component i have written code and set their properties in managed bean
  • look at managed bean code-

  • package dynamic.view.bean;
    
    import java.io.Serializable;
    
    import javax.faces.component.UIComponent;
    import javax.faces.event.ActionEvent;
    
    import oracle.adf.view.rich.component.rich.RichForm;
    import oracle.adf.view.rich.component.rich.input.RichInputText;
    import oracle.adf.view.rich.component.rich.input.RichSelectBooleanCheckbox;
    import oracle.adf.view.rich.component.rich.input.RichSelectOneRadio;
    import oracle.adf.view.rich.component.rich.layout.RichPanelFormLayout;
    import oracle.adf.view.rich.component.rich.nav.RichCommandButton;
    import oracle.adf.view.rich.component.rich.output.RichOutputText;
    import oracle.adf.view.rich.context.AdfFacesContext;
    
    public class DynamicCompBean implements Serializable {
    
        /**Parent component to add childs in it*/
        private RichPanelFormLayout panelFormLay;
    
        /**Binding to select which component should be created*/
        private RichSelectOneRadio compTypeBind;
    
        public DynamicCompBean() {
        }
    
        /**Method to add child to parent component*/
        public void addComponent(UIComponent parentUIComponent, UIComponent childUIComponent) {
            parentUIComponent.getChildren().add(childUIComponent);
            AdfFacesContext.getCurrentInstance().addPartialTarget(parentUIComponent);
        }
    
        /**Button code to generate and add components conditionally*/
        public void createComptext(ActionEvent actionEvent) {
    
            if (compTypeBind.getValue().toString().equalsIgnoreCase("I")) {
                RichInputText ui = new RichInputText();
                ui.setId("rit1");
                ui.setLabel("Input text");
                ui.setValue("Hello ADF");
                ui.setContentStyle("font-weight:bold;color:red");
                addComponent(getPanelFormLay(), ui);
            } else if (compTypeBind.getValue().toString().equalsIgnoreCase("O")) {
                RichOutputText ui = new RichOutputText();
                ui.setId("rot1");
                ui.setValue("I am output text");
                ui.setInlineStyle("font-weight:bold;color:green");
                addComponent(getPanelFormLay(), ui);
            } else if (compTypeBind.getValue().toString().equalsIgnoreCase("C")) {
                RichSelectBooleanCheckbox ui = new RichSelectBooleanCheckbox();
                ui.setId("ch1");
                ui.setValue(true);
                ui.setLabel("CheckBox");
                addComponent(getPanelFormLay(), ui);
            } else if (compTypeBind.getValue().toString().equalsIgnoreCase("B")) {
                RichCommandButton ui = new RichCommandButton();
                ui.setId("ch1");
                ui.setText("Button");
                ui.setInlineStyle("font-weight:bold;");
                addComponent(getPanelFormLay(), ui);
            }
    
        }
    
    
        public void setPanelFormLay(RichPanelFormLayout panelFormLay) {
            this.panelFormLay = panelFormLay;
        }
    
        public RichPanelFormLayout getPanelFormLay() {
            return panelFormLay;
        }
    
        public void setCompTypeBind(RichSelectOneRadio compTypeBind) {
            this.compTypeBind = compTypeBind;
        }
    
        public RichSelectOneRadio getCompTypeBind() {
            return compTypeBind;
        }
    }
    

  • Now run this application and select input text to create-

  • Select others also and create a form

  • You can create complex forms using this

         Download Sample workspace-Download Sample

Saturday, 27 July 2013

Implementing master/detail tree relation using af:Iterator and af:forEach for better UI designs - Oracle ADF

In ADF Faces tree and tree table is used for hierarchical representation of master/detail form of data,
in this tutorial i will show you that how can we design better UI's using master detail data.
af:iterator and af:ForEach both are used to iterate data as af:table for custom UI component-

here i am taking example of default HR Schema of Oracle database , Departments and Employees table to show master-detail relation

Using af:iterator-

  • Create a Fusion Web Application and prepare model for master detail relationship between departments and employees table, and in your page drop af:showDetailHeader from component palette
  • Go to page binding, add tree binding for Departments (Master) and Employees (Detail)


  • Surround showDetailHeader with an af:iterator,  and set value and var for iterator (master)

  •  Now change text of showDetailHeader to show department name on it, taking reference from iterator's var


  • master part is done, for detail part  drop two output text (for employee's first name and last name) inside showDetailHeader surrounding with an iterator (for detail part)




  • set the value and var for detail iterator taking reference from master iterator 

  • Now to show detail values in output text , set the value in both output text, taking reference from detail iterator


  • See the source of page for more clarification-

  • <af:iterator id="i3" value="#{bindings.Departments1.collectionModel}" var="departments">
                                    <af:showDetailHeader text="#{departments.DepartmentName}" disclosed="true" id="sdh1"
                                                         inlineStyle="width:350px;">
                                        <f:facet name="context"/>
                                        <f:facet name="menuBar"/>
                                        <f:facet name="toolbar"/>
                                        <f:facet name="legend"/>
                                        <f:facet name="info"/>
                                        <af:panelGroupLayout id="pgl2" layout="vertical">
                                            <af:iterator id="i2" var="emp" value="#{departments.Employees}">
                                                <af:separator id="s3"/>
                                                <af:panelFormLayout id="pfl1" rows="1">
                                                    <af:outputText value="#{emp.FirstName}" id="ot2"
                                                                   inlineStyle="font-weight:bold;color:darkblue;"/>
                                                    <af:outputText value="#{emp.LastName}" id="ot3"
                                                                   inlineStyle="font-weight:bold;color:red;"/>
                                                </af:panelFormLayout>
                                                <af:spacer width="10" height="10" id="s1"/>
                                            </af:iterator>
                                        </af:panelGroupLayout>
                                    </af:showDetailHeader>
                                </af:iterator>
    

  • Now Run your page to see UI of this master-detail relationship-


Using af:ForEach-

  •  Drop a panel accordion on page, by default it has one af:showDetailItem , surround it with af:ForEach and set items and var for ForEach

  • change text of showDetailItem to show department name on it, taking reference from ForEach's var 

  • Now drop Employees detail table from data control inside showDetailItem and set its value , taking reference from ForEach 


  • For more clarification see source of page-

  • <af:panelAccordion id="pa1" styleClass="AFStretchWidth" visible="true">
                                    <af:forEach items="#{bindings.Departments1.children}" var="dept">
                                        <af:showDetailItem text="#{dept.DepartmentName}" id="sdi1" inflexibleHeight="200">
                                            <af:table value="#{dept.children}" var="row"
                                                      rows="#{bindings.Employees3.rangeSize}"
                                                      emptyText="#{bindings.Employees3.viewable ? 'No data to display.' : 'Access Denied.'}"
                                                      fetchSize="#{bindings.Employees3.rangeSize}" rowBandingInterval="0"
                                                      filterModel="#{bindings.Employees3Query.queryDescriptor}"
                                                      queryListener="#{bindings.Employees3Query.processQuery}"
                                                      filterVisible="true" varStatus="vs"
                                                      selectedRowKeys="#{bindings.Employees3.collectionModel.selectedRow}"
                                                      selectionListener="#{bindings.Employees3.collectionModel.makeCurrent}"
                                                      rowSelection="single" id="t1" styleClass="AFStretchWidth">
                                                <af:column sortProperty="#{bindings.Employees3.hints.EmployeeId.name}"
                                                           filterable="true" sortable="false"
                                                           headerText="#{bindings.Employees3.hints.EmployeeId.label}"
                                                           id="c1">
                                                    <af:outputText value="#{row.EmployeeId}"
                                                                   shortDesc="#{bindings.Employees3.hints.EmployeeId.tooltip}"
                                                                   id="ot4">
                                                        <af:convertNumber groupingUsed="false"
                                                                          pattern="#{bindings.Employees3.hints.EmployeeId.format}"/>
                                                    </af:outputText>
                                                </af:column>
                                                <af:column sortProperty="#{bindings.Employees3.hints.FirstName.name}"
                                                           filterable="true" sortable="false"
                                                           headerText="#{bindings.Employees3.hints.FirstName.label}"
                                                           id="c2">
                                                    <af:outputText value="#{row.FirstName}"
                                                                   shortDesc="#{bindings.Employees3.hints.FirstName.tooltip}"
                                                                   id="ot5"/>
                                                </af:column>
                                                <af:column sortProperty="#{bindings.Employees3.hints.LastName.name}"
                                                           filterable="true" sortable="false"
                                                           headerText="#{bindings.Employees3.hints.LastName.label}" id="c3">
                                                    <af:outputText value="#{row.LastName}"
                                                                   shortDesc="#{bindings.Employees3.hints.LastName.tooltip}"
                                                                   id="ot6"/>
                                                </af:column>
                                                <af:column sortProperty="#{bindings.Employees3.hints.Email.name}"
                                                           filterable="true" sortable="false"
                                                           headerText="#{bindings.Employees3.hints.Email.label}" id="c4">
                                                    <af:outputText value="#{row.Email}"
                                                                   shortDesc="#{bindings.Employees3.hints.Email.tooltip}"
                                                                   id="ot7"/>
                                                </af:column>
                                            </af:table>
                                        </af:showDetailItem>
                                    </af:forEach>
                                </af:panelAccordion>
    


  • Now run your page to see its UI-


Download Sample workspace here- Download
Happy Jdeveloping..

Wednesday, 24 July 2013

Implementing custom search form in ADF programmatically (Without using af:query)

Sometimes we need to implement custom search instead of using adf query component.
To implement custom search form , i have used a quite beautiful way to handle search and reset functionality for a View Object.
In this post i am taking Employees Table (Default HR Schema) to search and reset af:table.

  • First create a Fusion Web Application and create model (EO,VO and AM) using Employees table
  • Now suppose we have to search on 4 fields (EmployeeId, FirstName, Email, Salary) , so for this i have created a new read only ViewObject from dual
  •  This VO from dual is created to be used as Search form on page
  •  Now to make search effective on Employees VO , i have created 4 bind variable for corresponding fields in Employees ViewObject



  •  Now i have created a ViewCriteria using these 4 bind variables to re-query ViewObject  data
  •  This ViewCriteria will be executed each time when value of bind variable is changed, now this is the time to set value of bind variables, so i have dragged dual vo as a form on page, and added 2 button for Search and Reset
  •  To View Search Result , Employees Table is there on page
  •  Now to get value from Form Field to bean , i have created binding for all 4 fields in bean
  •  Now i have created ActionListener for Search button- in this code i have get value from page using component bindings and passed in Employees ViewObject's bind variable in order to execute viewCriteria.

  •     public void searchButton(ActionEvent actionEvent) {
            searchAMImpl am = (searchAMImpl)resolvElDC("searchAMDataControl");
            ViewObject empVo = am.getEmployees1();
            empVo.setNamedWhereClauseParam("EmpIdBind", empIdPgBind.getValue());
            empVo.setNamedWhereClauseParam("FirstNmBind", firstNmPgBind.getValue());
            empVo.setNamedWhereClauseParam("EmailBind", emailPgBind.getValue());
            empVo.setNamedWhereClauseParam("SalaryBind", salaryPgBind.getValue());
            empVo.executeQuery();
        }
    

  • Once value is set in bind variable , view criteria is executed and Search result will be shown in resultant table- Run your application and see
  • To reset values in table and search form, see the managed bean code of Reset button

  •     public void resetButton(ActionEvent actionEvent) {
            searchAMImpl am = (searchAMImpl)resolvElDC("searchAMDataControl");
            ViewObject empVo = am.getEmployees1();
            ViewObject attrVo=am.getattr1();
            empVo.setNamedWhereClauseParam("EmpIdBind", null);
            empVo.setNamedWhereClauseParam("FirstNmBind", null);
            empVo.setNamedWhereClauseParam("EmailBind", null);
            empVo.setNamedWhereClauseParam("SalaryBind", null);
            empVo.executeQuery();
            attrVo.executeQuery();
          
        }
    

  • Click on reset button and page value are set to default

  • This is how we can implement custom search using ADF components, you can apply validations, auto suggest feature etc while using this custom search
          Cheers :-)  Download Sample App