Showing posts with label af:iterator. Show all posts
Showing posts with label af:iterator. Show all posts

Thursday, October 28, 2010

ADF UI: Pagination (Navigation using First, Previous, Next, Last buttons) using <af:iterator>

It was a tough time for me to achieve pagination (i.e., navigating through a set of records using First, Previous, Next, Last buttons) in one of my ADF pages. I searched in net for any solution, but finally convinced that there is no declarative way to achieve this functionality in ADF. And, I also found that this concept of pagination was declarative in OAF and this had been replaced by ADF table scroll navigation. So, I went ahead and did some research and developed my own pagination technique using <af:iterator>. The below steps explain the use case and how to achieve the same.

Sample Use Case:
For example, we have a list of employees (say 50) and we want to display 5 employees at a time and on clicking 'Next' button we want to display next 5 records and so on. Similarly, on clicking 'Previous' button we want to display previous 5 records. The 'First' and 'Last' buttons should take use to the first 5 records and last 5 records respectively.
One more challenge to this use case is that we want to disable the 'Previous' button, if there are no more previous records and vice versa. Similarly, we want to disable the 'First' and 'Last' buttons if the current list is first set or last set of records respectively. Achieving this would be little tricky and we'll see how we can implement it.

Implementation Steps:
Here, I'm going to use <af:iterator> component to iterate through list of employee records and display the sets of records. IF you want to know how to use af:iterator, read my previous post.

1. First, tune the VO which you want to iterate. Tuning the VO will give us better performance if we tune as per our page range size requirements in UI (Screenshot below).


2. Specify the 'rangeSize' for the VOIterator in pageDef as the no. of rows you want to display for each time you click on 'Previous' and 'Next'.  This represents rowSet size (In the below code, I'm setting it to 5).
<iterator Binds="EmpDeptVO" RangeSize="5" DataControl="DemoAMDataControl" id="EmpDeptVOIterator" ChangeEventPolicy="ppr"/>


3. Drop af:iterator into jsff and add all VO attributes under iterator (refer to previous post). Please find the below code. Here, in pagination, the attribute 'first' of af:iterator will play a major role. It'll actually specify starting from which row number, the data is to be displayed. By default, let's keep it 0. Later, we'll update it to move back and forth on clicking 'Previous' and 'Next' buttons.
<af:iterator id="i1" value="#{bindings.EmpDeptVO.collectionModel}" var="row" varStatus="i" rows="#{bindings.EmpDeptVO.rangeSize}" binding="#{pageFlowScope.ExampleBean.employeeIterator}">


4. Add buttons 'First', 'Previous', 'Next' and 'Last' and specify the actionListeners as below.

<af:toolbar id="t1" partialTriggers="i1"> <af:commandToolbarButton text="First" id="ctb2" actionListener="#{pageFlowScope.ExampleBean.firstClicked}" disabled="#{pageFlowScope.ExampleBean.previousDisabled}"/> <af:commandToolbarButton text="Previous" id="ctb1" actionListener="#{pageFlowScope.ExampleBean.PreviousClicked}" disabled="#{pageFlowScope.ExampleBean.previousDisabled}"/> <af:commandToolbarButton text="Next" id="commandToolbarButton1" actionListener="#{pageFlowScope.ExampleBean.nextClicked}" disabled="#{pageFlowScope.ExampleBean.nextDisabled}"/> <af:commandToolbarButton text="Last" id="ctb3" actionListener="#{pageFlowScope.ExampleBean.lastClicked}" disabled="#{pageFlowScope.ExampleBean.nextDisabled}"/> </af:toolbar>


public void firstClicked(ActionEvent actionEvent) { UIXIterator empIterator = getEmployeeIterator(); empIterator.setFirst(0); AdfFacesContext.getCurrentInstance().addPartialTarget(empIterator); } public void PreviousClicked(ActionEvent actionEvent) { UIXIterator empIterator = getEmployeeIterator(); int first = empIterator.getFirst() - empIterator.getRows(); empIterator.setFirst(first); AdfFacesContext.getCurrentInstance().addPartialTarget(empIterator); } public void nextClicked(ActionEvent actionEvent) { UIXIterator empIterator = getEmployeeIterator(); int first = empIterator.getFirst() + empIterator.getRows(); empIterator.setFirst(first); AdfFacesContext.getCurrentInstance().addPartialTarget(empIterator); } public void lastClicked(ActionEvent actionEvent) { UIXIterator empIterator = getEmployeeIterator(); int noOfRows = empIterator.getRowCount(); int first = noOfRows- noOfRows%empIterator.getRows(); empIterator.setFirst(first); AdfFacesContext.getCurrentInstance().addPartialTarget(empIterator); }

5. And to achieve enabling/disabling the buttons, I wrote the below method based on the total no. of rows and current row set.
public boolean isPreviousDisabled() { UIXIterator empIterator = getEmployeeIterator(); int first = empIterator.getFirst(); if (first <= 0) { return true; } return false; } public boolean isNextDisabled() { UIXIterator empIterator = getEmployeeIterator(); int first = empIterator.getFirst() + empIterator.getRows(); int noOfRows = empIterator.getRowCount(); if (first >= noOfRows) { return true; } return false; }


Now, run the page and you'll see first 5 records and you can navigate to different row sets using the navigation buttons. Sample screen shots below:


ADF UI - Easy implementation of editable forms using <af:iterator>

In this post, I'm going to show you how to use <af:iterator> to iterate through a list of employees and allow user to edit the employee details in a form. Sample application can be downloaded from here.

If you're new to using <af:iterator>, here are the simple implementation steps to convert <af:table> code to work with <af:iterator> to iterate through the VO rows referred by the table.

1. First, drop your VO which you want to iterate as <af:table> in your jsf page. </af:table>


<af:table value="#{bindings.EmpDeptVO.collectionModel}" var="row"                   rows="#{bindings.EmpDeptVO.rangeSize}"                   emptyText="#{bindings.EmpDeptVO.viewable ? 'No data to display.' : 'Access Denied.'}"                   fetchSize="#{bindings.EmpDeptVO.rangeSize}"                   rowBandingInterval="0" id="t2" width="100%"                   contentDelivery="immediate" autoHeightRows="10">


2. Now, drop <af:iterator> from component pallette and specify the values for properties  value, rows and var copying from <af:table> that you dropped.


<af:iterator id="i1" value="#{bindings.EmpDeptVO.collectionModel}"                      var="row" rows="#{bindings.EmpDeptVO.rangeSize}"                      varStatus="i">


3. Now, copy the attributes from table (which are under each column) into the <af:iterator> (from the sample application, you can see the attributes under af:iterator and af:table are same).

4. Arrange all these attributes in your preferred layout and run the page. That's it. You'll see each VO row data one by one. If you've dropped it as editable fields, you can edit them and Commit (as shown in the sample example).

That's it! Now, you understood how easy it is to implement editable forms using <af:iterator>. The sample output will be like this:
Related Posts with Thumbnails