Hook into client-side before POST UIDL changes?

Does V6 or V7 Vaadin have a hook for client side widgets to know when that end is getting ready to send updates back to the server?

We’d like our widget to be able to detect this so we can retrieve values that we may also want to send to the server. This is for a third-party widget that is embedded into pages/forms and we need a way to know when the client is considering sending updates (like because a button was pressed or the like) so we can check our javascript object for any new data values that can be sent too.

In Vaadin 7 it is really easy: your client-side widget should call ServerRpc method annotated with @Delayed(lastOnly=true) and these changes will be sent to the server when something is done that requires the changes to be sent immediately (button click, etc).
Also have a look at
Reducing server round trips for components
.

Thanks. Sadly, I’m not familiar yet with V7, but I can’t tell if this does what I’m talking about.

I am not sure if V6 has other mechanisms to know when to transfer data from the client back to the server or not (via ApplicationConnection.updateVariable). The examples I saw all seemed to use the field’s BLUR event to check if the value changed and, if so, it calls that updateVariable() method, with a flag indicating whether it should be ‘immediate’ or not.

I have a client side widget that has no good “blur” event, so I am trying to find out if there’s any way to hook into the Vaadin client side to know when a transfer is either about to take place, or perhaps when a given button is clicked. That is, my widget will be in a Form, and we have a Save Button for the Form. When the Save button is clicked, I’d like to somehow query my client side widget at the same time the client side is processing that button click so I can tell if data changes need to be sent or not. If it’s changed, I’d just call updateVariable() as before, ensuring that my updated widget data goes with the Save button click.

My widget has its own Save button, and that’s reliable, but it’s not helpful from a UI perspective because if they click the Save button on the Form, it needs to just work rather than saying they first have to save my widget, then save the form.

Does the V6 client side have any such list of all fields that it can query when a button is pressed?

Hi,

AFAIK there are no hooks for this, but according to
this ticket
it should be possible to add your own. I guess the method you’d want to look at might be sendPendingVariableChanges(). Seems to me that you could just override that in your own extension of the ApplicationConnection (via deferred binding), call any hooks you want (and have registered) and then just call the same method from the super class.

Disclaimer: I haven’t actually tried this out.

-tepi

This is promising, as it seems to work in my test application used for the widget.

But when I export the widget to a JAR and include in my regular project, it seems to behave oddly. For example, it seems that my Widget is having its onUnload() method called when it shouldn’t be. Maybe there’s something more subtle going on when I override the ApplicationConnection with my own subclass.

This is what I’m trying now:

public class MyApplicationConnection extends com.vaadin.terminal.gwt.client.ApplicationConnection {

	LinkedList<VCKEditorTextField> editorList = new LinkedList<VCKEditorTextField>();
	boolean processingEditorList = false;
	
	public void addEditor(VCKEditorTextField editor) {
		synchronized(editorList) {
			if ( ! editorList.contains(editor) )
				editorList.add(editor);
		}
	}
	
	public void removeEditor(VCKEditorTextField editor) {
		synchronized(editorList) {
			editorList.remove(editor);
		}
	}
	
    @Override
    public void sendPendingVariableChanges()
    {
    	// This flag is used because if the editor does send data, it will create recursive calls, so this stops that.
    	if ( processingEditorList )
    		return;
		
    	synchronized(editorList) {
			processingEditorList = true;
			for( VCKEditorTextField editor : editorList )
				editor.checkIfNeedsToSendToServer();
			processingEditorList = false;
		}
		
    	// Do the real one!
        super.sendPendingVariableChanges();
    }
}

Okay, I found that if my callback doesn’t say it’s immediate, I can avoid the recursive calls to ApplicationConnection.sendPendingVariableChanges().

But what I see now is that it appears my button is being sent along with the new data values, which I can see in this GWT debug statement:

00:09:52.254 [INFO]
 Making UIDL Request with params: cb18fb07-6504-492f-9c02-60e7338cf3detruePID119stateb1,249,863,false,false,false,false,1,51,9PID119mousedetailss<h1>aaa</h1> PID132texts

PID132 is my widget paintableId, the field name is ‘text’ and the value sent is ‘

aaa

’. But somehow, on the server side, my Form is processing the SAVE button click before my field is updated since when I call Form.commit() the field still shows the old value. And only then do I see my server-side component’s changeVariables() callback being called. So, while it seems I’m sending along my data with that request, the Form is processing the button before my server-side widget is being updated by the changeVariables() call.

Unfortunately, ApplicationConnection.pendingVariables is private, so I cannot use my subclass to ensure my widget values are before others in the ArrayList. I think the server side is just processing them in order, so the button is firing before my data update. It’s sad that so many classes use private instead of protected, thus making it impossible to subclass when subclassing is what makes object oriented programming so cool.

What might I be missing in trying to hook into the ApplicationConnection? My current subclass is even simpler now:

public class MyApplicationConnection extends com.vaadin.terminal.gwt.client.ApplicationConnection {

	LinkedList<VCKEditorTextField> editorList = new LinkedList<VCKEditorTextField>();
	
	public void addEditor(VCKEditorTextField editor) {
		synchronized(editorList) {
			if ( ! editorList.contains(editor) )
				editorList.add(editor);
		}
	}
	
	public void removeEditor(VCKEditorTextField editor) {
		synchronized(editorList) {
			editorList.remove(editor);
		}
	}
	
    @Override
    public void sendPendingVariableChanges()
    {
    	synchronized(editorList) {
			for( VCKEditorTextField editor : editorList )
				editor.checkIfNeedsToSendToServer();
		}
		
    	// Do the real one!
        super.sendPendingVariableChanges();
    }
}