JDeveloper & ADF: Reset Form Fields

In the last couple of weeks I saw some posts on JDeveloper & ADF forum asking how to reset form fields when the user had changed some or all fields of an input form and wants to undo the changes. This is a typical use case when you work with forms to enter or change data.

In this blog I summarize the different possible solutions build in the ADF framework. The sample provided for you to analyze is build using JDeveloper and uses the HR schema. A link to download the workspace is provided at the end of the blog post.

Before I go into the different solutions, I like to point out that all solutions can only reset values to the last data model state if they are not submitted. After a value is submitted the reset operation will show the same value as in the UI. If you e.g. navigate to the next record all values are submitted to the data model (not the db). Calling reset after you go back to the previous record you’ll see no change as the values are already submitted.
As an implication you need to make sure that the action component (button, listener…) uses the immediate property set to ‘true’. If the immediate property is set to ‘false’ the action first updates the model after which no reset is possible. In this case you can only rollback the transaction to get the old values back.

Lets start with a picture of the running application:

Running Applicaiton

Running Applicaiton

As you see it’s just the employees table dropped as adf form on a jsf page with navigation buttons and an other row of buttons to demonstrate the different possible solution for the use case. First I show how to use java code in a bean to reset the changes made in the form. Next I use a command button with an af:resetActionListener attached. Then there is the new af:resetButton which was introduced in JDev and is essentially like the previous solution. As a variation I added two buttons which I use to queue an action from inside a bean method to the second and third buttons. Finally there is cancel button which does a rollback of the transaction. This rollback undo changes even if you navigate back and forth over the row set.

1. Reset field from a java bean

The button ‘Reset Form Fields by Bean’ uses an action listener to call a method in a request scope bean. This method then resets the form fields using the ResetUtils.reset(UIComponent start); method to do the work.

    public void resetFormFieldsListener(ActionEvent actionEvent)
        // check if hte action has a component attatched
        UIComponent uiComp = actionEvent.getComponent();
        if (uiComp == null)
            // if not we use the button which we bound to this bean
            _logger.info("reset fields: buttonID = " + uiComp.getId());
            _logger.info("reset fields: CompID = " + uiComp.getId());
        // pass component inside the UIForm, UIXForm, UIXSubform, UIXRegion, UIXPopup, RichCarousel
        // or RichPanelCollection which holds the components to reset

The ResetUtils.reset(UIComponent start) method walks up the component tree to find the first UIForm, UIXForm, UIXSubform, UIXRegion, UIXPopup, RichCarousel or RichPanelCollection component. Any one of this components are used as container elements for input components (inputText, inputDate …) which are reset to the values stored in the model data. This allows to only reset part of the input components on a page. So passing the right start component to the reset method is essential. In the simple layout I used in the sample it’s OK to use the button which has the actionListener attached. The af:form is the container found by the ResetUtils.reset(UIComponent start) method.
The ResetUtils.reset(UIComponent start); can be used from other bean code too. In this case you need to set a component as start component. Which component you use depends on your page layout.

Solution 1 ResetUtils.reset(...)

Solution 1 ResetUtils.reset(...)

2. Command button with attached resetActionLitener

This was the default solution in JDev 11.1.1.x.0. You attach an af:resetActionListener to an other command component and when an action is triggered the reset take place. See solution 4 for a variation.

        <af:commandButton actionListener="#{bindings.Rollback.execute}"
            text="Cancel" immediate="true" id="cb6">
Solution 2: af:resetActionListener

Solution 2: af:resetActionListener

3. af:resetButton
This component was introduced with JDev and works like a command button with an attached af:resetActionListener. Advantage is that you have only the button, nothing attached which makes it more clear to understand.



<af:resetButton text="Reset Form Fields" id="rb1" binding="#{BRFFBean.buttonResetButton}"/>
Solution 3: af:resetButton

Solution 3: af:resetButton

4. Queue an action to a button with attached af:resetActionListener

This solution is a combination of the first one using java code which then queues an action on an existing button on the page. If this button has an af:resetActionListener attached it resets the form fields as if the user had hit the button itself. On the page I use a button with an actionListener simply to get to a bean method (an actionListener in this case)

<af:commandButton text="Queue Action1 " id="cb9"

and in the bean I queue an action to the button with the attached af:resetActionLisener. This button is bound to a bean property to keep things simple.

    public void queueAction1Listener(ActionEvent aEvent)
        _logger.info("Queue action for button wiht af:resetActionListener");
        ActionEvent actionEvent = new ActionEvent(this.getButtonResetActionListener());
Solution 4: Queue action to existing button with af:resetActionListener

Solution 4: Queue action to existing button with af:resetActionListener

5. Queue an action to a af:resetButton

Like in solution 4 I use an existing button (the af:resetButton in this case) and queue an action on this button using java code in a bean.

<af:commandButton text="Queue Action2" id="cb10"

and the code in the bean looks like in solution 4, only the button the action is queued on differs.

    public void queueAction2Listener(ActionEvent aEvent)
        _logger.info("Queue action for af:resetButton");
        ActionEvent actionEvent = new ActionEvent(this.getButtonResetButton());

Now, if you carefully look at the result of this action you’ll notice that nothing has happened. I filed an SR for this, resulting in bug 13802277 ‘QUEUEING AN ACTION EVENT ON AN RICHRESETBUTTON DOESN’T WORK’.

Solution 5: Queue action on af:resetButton

Solution 5: Queue action on af:resetButton

6. Cancel action with rollback

This solution just call the rollback of the data control. This give you the values back which are stored in the DB. This allows even to reset changes which where submitted to the data model, but where not persisted in the db.

You can download the sample workspace, build with JDev and depending on the HR db schema, from here: BlogRestFormFields.zip.doc
Please rename the file to ‘.zip’ after downloading it!


5 thoughts on “JDeveloper & ADF: Reset Form Fields

  1. Hi Timo,

    there is a typo on 2. The following codesnippet

    corresponds to (6. Cancel action with rollback)

    Codesnippet for solution 2. should be without actionListener=”#{bindings.Rollback.execute}”.

    Great summary. Thx!

  2. Hi! Great article! Very Helpful!

    The core rollback looks very intrusive to me… Do you know any way to rollback the changes while keeping the current iterator row???

    In example:
    If you list employees from a departament and delete one employee, after pressing rollback you’ll get to the first deparment row, sounds really weird to me…

    • This is not weird. A rollback undo all changes made from the point of the last commit. This can be numerous changes in different VO or EO. Furthermore after a rollback you get changes made other users into the data you currently see. An other user might have deleted the row (the department in your sample) in the time you took to do your work.
      As Web applications normally work with optimistic locking, you notice this first when you try to commit your changes.
      In summary you can’t be sure if the department row is still available. The framework thus resets all iterators back to the first row, or before the fist row if there is no row left.

      If you want to keep the row you are working on, you must store the pk of this row, then do the rollback and restore the row using the saved pk.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s