Dirty Form Flag in GWT or basically how to identify if in the form if there are any unsaved changes

1,296 views
Skip to first unread message

BM

unread,
Jan 29, 2013, 4:26:29 PM1/29/13
to google-we...@googlegroups.com
I have a form in GWT and I want to capture an event similar to dirtyform flag in JQuery. Basically I want to understand if any of the form data has been changed. The requirement is pretty simple here. I am NOT looking for if the data has been actually been modified but just to find out if they touched my form data by any way.

So let's say if my form has one GWT Textbox and one ListBox. For me the form data is changed with any of the following condition:

1) If the user changes the value inside Textbox and revert it back to previous original value. 
2) The user changes the default selection of ListBox to new selection but changes back to default selection.
3) If the user changes the value inside Textbox to a new value.
4) The user changes the default selection of ListBox to new selection.

The form data is not changed if the user just views the form but did not change any of the values in the Widgets at all. 

One way I thought would be to use onChange event and set a local flag hasDataChanged to true. Once the flag hasDataChanged has been set to true then don't reset it as it means the user touched the form. Based on the value of flag hasDataChanged show an alert message when navigating away from the page. 

But my problem is that if there are more GWT user interaction widgets (let's say 15 TextBox, 5 ListBox), the UI will fire onChanged Event every time. Plus I have to add onChange event handler to all of my GWT widgets. 

Perhaps there is a better way to do handle this. May be on view level if there is a single event I can assign which knows if any of GWT widgets been touched by the user? 

Any help would be appreciated!

Rob Whiteside

unread,
Jan 29, 2013, 5:43:35 PM1/29/13
to google-we...@googlegroups.com
The GWT Editor Framework does stuff with isDirty().  But by default it just compares your UI fields to the underlying model.  So that won't cover your cases 1 and 2.  You'd need to add some custom code to handle those cases.  The only way I can think to do that is by listening for events.

WIth UIBinder it wouldn't be too too bad... something like:

@UiHandler(value = {"tbox1", "tbox2", ... "tboxn"})
public void onTextBoxBlur(BlurEvent e) {
  //set dirty flag ...
}

that would listen for your blur event from all those textboxes.

Another thought would be to subclass textbox and handle it in there by adding an isDirty() flag

BM

unread,
Jan 29, 2013, 7:11:44 PM1/29/13
to google-we...@googlegroups.com
Thanks Rob for the reply. Point 1 and 2 are really not important. I put it there as I really don't want to check every field and see if any value is really actually changed or not. 

I haven't used Editor framework though. Not sure how easy it is to implement existing forms done thru GWT event handling and RPC.

I thought about the onBlur Event or onChange Event but what if I have dynamic implementation of textboxes based on data coming from the server? Adding a separate ValueChangeEvent handler may require adding an event handler for every textbox which is not efficient I believe and may use up memory. Also if I add checkboxes, Radios, ListBoxes, I have to manually handle all the events and write custom code to manage the isDirty method. 

On top of that I use MVP framework with Activities and Places. 

With all I had said so far, what I really want to show user pop-up message if they navigate away from the current form to a different Place  or different tab within the same place  (Parent Activity and various child Activities and Parent Activity loads one child Activity at a time which loads its View accordingly but the place remains same. This is handle with the variable used inside the Parent place. Example : AdministrationPlace:addUser, AdministrationPlace:listUser, AdministrationPlace:assignRoles) 

Any help would be appreciated. 

Gustavo Rodríguez

unread,
Aug 28, 2013, 7:59:00 AM8/28/13
to google-we...@googlegroups.com
Hi BM,
I am trying pretty much the same thing ... did you find a generic and performant approach to it? I am thinking of exploring the DOM and adding an event handler to every widget ... but well, that might not be good for performance, so i would appreciate your comments if you already dealed with this before.
Thanks!

jaga

unread,
Aug 29, 2013, 5:05:49 PM8/29/13
to google-we...@googlegroups.com
Hi,

I think a good way to achieve this is to compare the model objects. I will explain the approach as follows:
1) on starting the screen make a copy of the object to be edited - I presume this is downloaded via an RPC or similar.
2) edit the object. Every time a field changes update the object.
3) if the screen is about to change compare the edited object with its copy. I suggest you override Java equals().
4) if there is a difference then display a warning. The Places Activities has a mechanism to detect changes.

Best regards,

Gustavo Rodríguez

unread,
Aug 30, 2013, 4:33:01 AM8/30/13
to google-we...@googlegroups.com
Thx for the suggestion Jaga. Your solution has the advantage that the UI composition, potentially containing fields irrelevant to the model, can be ignored and is centered on the model changes themselves, sounds good.
Thank you!

Steve C

unread,
Aug 30, 2013, 9:14:21 AM8/30/13
to google-we...@googlegroups.com
jaga,

If you're going to update the model object with every change, then it seems that you'd need a value change handler on every form field.

I've usually implemented this concept by having a single inner class ValueChangeHandler instance for the form composite, along with a boolean dirty field.  The handler gets added to every form field. Given that there's a single handler instance, I don't think that takes up too much memory. You can cut down the amount of code you have to write by creating a utility method, something like addWithHandler(HasValueChangeHandlers widget, ValueChangeHandler handler) that adds the handler to the widget and then delegates to the panel's add method - with appropriate variations for panels that have parametrized add methods.

In the onValueChange method I check the dirty flag - if it's false, I set it to true and fire a custom DataDirty event (which is just a simple custom event with no special fields - usually the only thing I'm interested in is the event source, which I can get from the inherited getSource method). Then my external logic can add whatever I want as a handler.

That way, my model bean stays in it's original condition until I go to save the form data, from something like a Save button click. That way, I don't have to worry about any external references to the same bean "seeing" the changes before I want them to. And with a Cancel button click I can just repopulate the form from the model object. The dirty field gets set back to false upon loading, saving, or cancelling.
Reply all
Reply to author
Forward
0 new messages