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

Sharing is Caring

In ADF Faces tree and tree table is used for the 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 the example of default HR Schema of Oracle database, Departments and Employees table to show the master-detail relation

Using af:iterator-

  • Create a Fusion Web Application and prepare the model for the master-detail relationship between departments and employees table and in your page drop af:showDetailHeader from the 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 the 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 the 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 the 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 the page, by default it has one af:showDetailItem , surround it with af:ForEach and set items and var for ForEach

    af:Iterator and af:forEach
  • Change the 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 the source of the 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
Cheers 🙂 Happy Learning 

Related Posts

An Oracle ACE, Blogger, Reviewer, Technical Lead working on Oracle ADF

0 thoughts on “Implementing master/detail tree relation using af:Iterator and af:forEach for better UI designs – Oracle ADF”

  1. Hi Ashish,

    Very nice blog, thanks for sharing this tip,

    I have one use case, can you please help me with that,

    I have Associations and view links between following entities in BC Layer:
    Department(Parent:1) and Employees (child: Many),
    Employees(Parent: 1) and Job history (child: Many).

    In JSFF:

    I have a form layout with two fields mapped from Department VO and then

    underneath it I have a iterator on Employees collection similar to the use case you provided here in first part of this blog and I surrounded showDetailHeader with the iterator (defined proper partial triggers on iterator for refreshing showDetailHeader area for inserting a new row in Employees via createinsert method from command image link and),

    now I have a requirement to show child table(Job history) data inside showDetailHeader: when I drag and drop the View Link(Job history) from data controls to jsff under the main iterator (for parent collection below Department form fields) & showDetailHeader it is not working as expected, Binding repeats for multiple parent rows.

    when I do create insert on parent(Employees) it shows blank rows in child table(Job history) for existing Employee rows,

    here we are dealing with Parent–>Child1(Association and VL between Parent and Child1 defined)
    –>Child2(Association and VL between Child1 and Child2)

  2. Hi Ashish

    I have same implementation in one of my application its working fine as expected. Everything is fine for now. But i have a refresh issue with child table. I attached sample application link also.

    For example

    Like your second application i have implemented Departments and Employees Relations ship

    I placed two execute with parms one is for filtering departments based on ID and others for employees based on hire date.

    Departments filter is working fine but employees filter not working properly.
    Its filtering data but the table not refreshing its data.

    can you please help me on this issue.
    here is the Sample Application Link :
    https://www.dropbox.com/s/p82nyh4r0s7lrnn/Iterator.zip?dl=0

    Thanks
    Praveenraj M90

  3. Hi Asish,
    Thanks for your reply i tried the above solutions but its not working my problem is its refreshing iterator but in UI am getting problem it was not refreshing in any way.

    Thanks
    Praveenraj M90

Leave a Reply

Your email address will not be published. Required fields are marked *