Skip to main content

ADF 11g : Using the ActiveRowKey property

In ADF 11g Release 2, the ADF Table component has a property called 'ActiveRowKey'. According to documentation, this represents the row that is currently active on the client. In click-to-edit mode, the active row will be made editable and is brought into view (if not already visible). Upon initial display, the click-to-edit component defaults the active row to the first visible row.

In this post I will show you how to use the activeRowKey programmatic.

Use Case.

Imagine the following use case: I have a 'click-to-edit' table and I added a 'filter' field with a button in the surrounding panel collection. User enters (in this case) a last name and pushes the button. The table scrolls to the first row that matches the criteria, and the row is active to edit.

Implementation.

I create an ADF table based on ADF business components for the Employees table.
It's a clickToEdit table with singleSelection. After creating it I bind it to a bean. I'll show later why I need to do that. The table code looks like this:
1:        <af:table value="#{bindings.Employees1.collectionModel}" var="row"  

2: rows="#{bindings.Employees1.rangeSize}"
3: emptyText="#{bindings.Employees1.viewable ? 'No data to display.' : 'Access Denied.'}"
4: fetchSize="#{bindings.Employees1.rangeSize}"
5: rowBandingInterval="0"
6: selectionListener="#{bindings.Employees1.collectionModel.makeCurrent}"
7: rowSelection="single" id="t1" editingMode="clickToEdit"
8: selectedRowKeys="#{bindings.Employees1.collectionModel.selectedRow}"
9: binding="#{pageFlowScope.empsBean.empTable}">
10: <af:column ............................


Next I surround it with a panel collection and I turn off a lot of features (also new in R2) of the panel collection. In the toolbar facet I add an inputText component and a commanfbutton. The inputtext will hold the search value, and the button invokes logic to scroll the table and make to row active.

1:       <af:panelCollection id="pc1" featuresOff="viewMenu detach" >  

2: <f:facet name="menus"/>
3: <f:facet name="toolbar">
4: <af:toolbar id="t2">
5: <af:group id="g1">
6: <af:inputText label="enter last name" value="#{pageFlowScope.empsBean.searchValue}" id="it11"/>
7: <af:commandToolbarButton text="goto employee" id="ctb1"
8: actionListener="#{pageFlowScope.empsBean.gotoPressed}"/>
9: </af:group>
10: </af:toolbar>
11: </f:facet>


In the actionListener I first get a hold of the RowSetItetator. For each and every row in the rowSetIterator, I check if it matches the entered search string. I do that in a separate method called matchFound() (see line 8).

1:   public void gotoPressed(ActionEvent actionEvent) {  

2: // Add event code here...
3: DCIteratorBinding it = ADFUtils.findIterator("Employees1Iterator");
4: RowSetIterator rsi = it.getRowSetIterator();
5: RowKeySet oldSelection = empTable.getSelectedRowKeys();
6: if (rsi.first() != null) {
7: Row r = rsi.first();
8: while (rsi.hasNext() && getKey() == null && (!matchFound(r,oldSelection))) {
9: r = rsi.next();
10: }
11: }
12: }


In the matchFound() method I compare the value of the LastName attribute with the value entered by the user (see line 7). If it is a match there are two more things I need to do. First I add the key of the row found to be the activeRowKey (see line 11). Finally I need to make the row current. If I dont do this, it will still work, but by making the row current, it just looks a lot nicer. The trick I use here (see line 13) is a method (line 18) that I borrowed from Frank Nimphius' blog.

1:   private boolean matchFound (Row r,RowKeySet oldSelection){  

2: setKey(null);
3: ArrayList lst = new ArrayList(1);
4: RowKeySetImpl newSelection = new RowKeySetImpl();
5: Key key = null;
6: String rowValue = (String)r.getAttribute("LastName");
7: if (rowValue.toString().contains(searchValue)) {
8: System.out.println("now setting key to " + key);
9: key = r.getKey();
10: lst.add(key);
11: empTable.setActiveRowKey(lst);
12: newSelection.add(lst);
13: makeCurrent(empTable, newSelection, oldSelection);
14: return true;
15: }
16: return false;
17: }
18: private void makeCurrent(RichTable empTable, RowKeySet newCurrentRow, RowKeySet oldCurrentRow) {
19: //To make a row current, we need to create a SelectionEvent which
20: //expects the following arguments: component, unselected_keys,
21: //selected_keys. In our example, we don't have unselected keys and
22: //therefore create an empty RowSet for this
23: SelectionEvent selectionEvent =
24: new SelectionEvent(oldCurrentRow, newCurrentRow, empTable);
25: selectionEvent.queue();
26: AdfFacesContext.getCurrentInstance().addPartialTarget(empTable);
27: }


The works.

Start the application, type some searchText, push the button and of you go.


The row is found, and immediate available for edit.


Resources.

ADF Code Corner Oracle JDeveloper OTN Harvest

A copy of the workspace for this post can be downloaded here.

Comments

Timo said…
Nice work!
Hint for uploading the workspace (which I use on wordpress):
zip it, rename it to .jpg and upload it as image

Timo
Luc Bors said…
Thanks Timo, I'll try that trick for uploading the workspaces
giovanni said…
The property is very interenting, can you send me your test wkj?

thank Gio.
Zee said…
Nice post luc. You can host your apps at code.google.com like i do

http://code.google.com/p/orclsamples
Luc Bors said…
This comment has been removed by the author.
Luc Bors said…
Thanks for the tip. I think google code can be an excellent place to host my workspaces. I'll try that soon.
Luc Bors said…
I decided to host my workspaces at google code. The workspace for this post is now available at http://adfsamplecode.googlecode.com/files/activeRowKey.zip
Anonymous said…
Hi, could you explain the need to use key to null at the first step of matchFound
Anonymous said…
setActiveRowKey does not work in 11.1.1.6.

Has anyone tried it?

Popular posts from this blog

ADF 12.1.3 : Implementing Default Table Filter Values

In one of my projects I ran into a requirement where the end user needs to be presented with default values in the table filters. This sounds like it is a common requirement, which is easy to implement. However it proved to be not so common, as it is not in the documentation nor are there any Blogpost to be found that talk about this feature. In this blogpost I describe how to implement this. The Use Case Explained Users of the application would typically enter today's date in a table filter in order to get all data that is valid for today. They do this each and every time. In order to facilitate them I want to have the table filter pre-filled with today's date (at the moment of writing July 31st 2015). So whenever the page is displayed, it should display 'today' in the table filter and execute the query accordingly. The problem is to get the value in the filter without the user typing it. Lets first take a look at how the ADF Search and Filters are implemented by

How to: Adding Speech to Oracle Digital Assistant; Talk to me Goose

At Oracle Code One in October, and also on DOAG in Nurnberg Germany in November I presented on how to go beyond your regular chatbot. This presentation contained a part on exposing your Oracle Digital Assistant over Alexa and also a part on face recognition. I finally found the time to blog about it. In this blogpost I will share details of the Alexa implementation in this solution. Typically there are 3 area's of interest which I will explain. Webhook Code to enable communication between Alexa and Oracle Digital Assistant Alexa Digital Assistant (DA) Explaining the Webhook Code The overall setup contains of Alexa, a NodeJS webhook and an Oracle Digital Assistant. The webhook code will be responsible for receiving and transforming the JSON payload from the Alexa request. The transformed will be sent to a webhook configured on Oracle DA. The DA will send its response back to the webhook, which will transform into a format that can be used by an Alexa device. To code

ADF 11g Quicky 3 : Adding Error, Info and Warning messages

How can we add a message programatically ? Last week I got this question for the second time in a months time. I decided to write a short blogpost on how this works. Adding messages is very easy, you just need to know how it works. You can add a message to your faces context by creating a new FacesMessage. Set the severity (ERROR, WARNING, INFO or FATAL ), set the message text, and if nessecary a message detail. The fragment below shows the code for an ERROR message. 1: public void setMessagesErr(ActionEvent actionEvent) { 2: String msg = "This is a message"; 3: AdfFacesContext adfFacesContext = null; 4: adfFacesContext = AdfFacesContext.getCurrentInstance(); 5: FacesContext ctx = FacesContext.getCurrentInstance(); 6: FacesMessage fm = 7: new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, ""); 8: ctx.addMessage(null, fm); 9: } I created a simple page with a couple of buttons to show the result of setting the message. When the but