Why does a Viewer not update after Editor edits a Property?

Following the examples in the Book of Vaadin
page on Properties
, I created an ObjectProperty, with both a Viewer and Editor of that property in a Window.

The Book of Vaadin says the Viewer should update automatically when the Editor edits.

But not so in my attempt.

When the user edits the Property using the Editor, the Viewer does not get updated on screen automatically. If some other redraw occurs, such as a Button causing some other Label to get a new value, then the Viewer re-displays properly.

==> Why does the Viewer (Label) not get updated when the Editor (TextField) edits?

I tried setting the window’s Immediate mode to True. Did not help.
I tried setting the TextField’s WriteThrough to True. Did not help. (Already the default)

I wrote a simple example, complete in a single class.

Here’s the core part, creating the Property, Viewer, and Editor.

        String initTime = new java.util.Date().toString(); // Get the current datetime.
        prop = new ObjectProperty( initTime, String.class ); // Our data model. Initialize with current datetime.

        // Create a Label to view our Property.
        viewer = new Label(); // Component that implements com.vaadin.data Property.Viewer
        viewer.setCaption( "Current value of prop:" );
        viewer.setPropertyDataSource( prop ); // Bind it to the data
        mainWindow.addComponent( viewer );

        // Create a TextField to edit our Property.
        editor = new TextField( "this string should NOT appear on screen" ); // Component that implements com.vaadin.data Property.Editor
        editor.setCaption( "Set my property:" );
        editor.setPropertyDataSource( prop ); // Bind the Property to the Editor.
        //editor.setWriteThrough( true ); // True is the default.
        mainWindow.addComponent( editor );

And here’s the entire class, to replace the contents of the class created by the Vaadin Eclipse plugin’s New Vaadin Project:

package com.example.propertyexperiment;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import com.vaadin.Application;
import com.vaadin.data.Property;
import com.vaadin.data.util.ObjectProperty;
import com.vaadin.ui.*;

public class PropertyexperimentApplication extends Application implements Button.ClickListener {
    Property prop = null;
    Label viewer = null;
    TextField editor = null;
    
    Button nowButton = null;
    Label nowLabel = null;

    @Override
    public void init() {
        Window mainWindow = new Window( "Propertyexperiment Application" );
        Label label = new Label( "Hello Bonjour Vaadin user" );
        mainWindow.addComponent( label );
        
        //mainWindow.setImmediate( true ); // Does not help make the Viewer update after Editor edits.

        String initTime = new java.util.Date().toString(); // Get the current datetime.
        prop = new ObjectProperty( initTime, String.class ); // Our data model. Initialize with current datetime.

        // Create a Label to view our Property.
        viewer = new Label(); // Component that implements com.vaadin.data Property.Viewer
        viewer.setCaption( "Current value of prop:" );
        viewer.setPropertyDataSource( prop ); // Bind it to the data
        mainWindow.addComponent( viewer );

        // Create a TextField to edit our Property.
        editor = new TextField( "this string should NOT appear on screen" ); // Component that implements com.vaadin.data Property.Editor
        editor.setCaption( "Set my property:" );
        editor.setPropertyDataSource( prop ); // Bind the Property to the Editor.
        //editor.setWriteThrough( true ); // True is the default.
        mainWindow.addComponent( editor );
        
        TextField ignoreTextField = new TextField("whatever");
        ignoreTextField.setCaption( "Ignore this field - here to accept focus:" );
        mainWindow.addComponent( ignoreTextField );
        
        nowLabel = new Label("the now label");
        nowButton = new Button("Now:");
        nowButton.addListener( this );
        mainWindow.addComponent( nowButton );
        mainWindow.addComponent( nowLabel );

        setMainWindow( mainWindow );
    }
    
    public void buttonClick(Button.ClickEvent event) {
        String newValue = new java.util.Date().toString();
        nowLabel.setValue( newValue );
    }

}

Using Vaadin 6.7.2, Eclipse Indigo Service Release 1, Vaadin plugin 2.0.1.201105170102, Java 1.6.0_29, Mac OS X 10.6.8.

The book says that the caption will be updated “once it loses the focus” not at every key pressed.

Vaadin is a server driven framework. So for something to happen the client browser needs to inform the server that something happened.
As communicating with the server needs to send packets through internet, server processing, … Vaadin tries to send as few updates as possible not to overload the server and the network.

As most of the time text fields are used to type some data and then press a “submit” button before something happens the Vaadin developers decided it was too much load to send and require from the server some processing for every key every user would press.

Sometimes it is needed to react to every key press (for instance for updating a list of suggestion next to a search box) and in that case you can use the
SuperImmediateTextField

Thanks for replying, but no, I’m not talking about key presses. I’m talking about losing focus. Note the extra TextField labeled “Ignore this field - here to accept focus”.

If I press Return, or Tab into the next TextField, the Viewer (Label) is not updated. This runs contrary to the Book of Vaadin saying “…the viewer… is updated immediately after … editor … loses focus”.

–Basil Bourque

[right]

[/right]The editor needs to be set to “immediate” - see the code in last paragraph of section
9.2.1 in the Book Of Vaadin

i.e.

editor = new TextField("this string should NOT appear on screen"); // Component that implements com.vaadin.data Property.Editor
    editor.setCaption("Set my property:");
    editor.setImmediate(true);
    editor.setPropertyDataSource(prop); // Bind the Property to the Editor.
    //editor.setWriteThrough( true ); // True is the default.
    mainWindow.addComponent(editor);

Cheers,

Charles.

Thank you Charles Anthony for correcting me. I’m a dope – I read and quoted the Book’s source code comments but failed to notice the crucial line of code below it:

editor.setImmediate(true);

Of course the Viewer’s display cannot be updated if the Editor’s edits have not been conveyed to the server-side app “immediately”.

As penance, I corrected my example code posted above. I tried to make it a useful example based on the Book of Vaadin’s discussion of Properties, for posterity.

package com.example.propertyexperiment;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import com.vaadin.Application;
import com.vaadin.data.Property;
import com.vaadin.data.util.ObjectProperty;
import com.vaadin.terminal.Sizeable;
import com.vaadin.ui.*;

/**
 * This single-class Vaadin program can help educate programmers new to Vaadin's data-binding technology by demonstrating:
 * (a) Creation of a Property, and attaching that Property as a data source to GUI widgets.
 * (b) How a Property can be attached both a Viewer and Editor in a window.
 * (c) How a Viewer's display is updated with the Editor's edits only when the Editor's Immediate mode is set to 'true'.
 * 
 * To see that last item (Immediate mode's effects), check and uncheck the checkbox while typing in the Editor TextField.
 * See the Book of Vaadin: https://vaadin.com/book/-/page/datamodel.properties.html
 * 
 * Posted: https://vaadin.com/forum/-/message_boards/view_message/939487
 * Built & tested with Vaadin 6.7.2, Mac OS X 10.6.8, Eclipse Indigo Service Release 1, Vaadin Eclipse plugin 2.0.1.201105170102.
 * 
 * © 2011 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
 * 
 * @author Basil Bourque
 *
 */
public class PropertyexperimentApplication extends Application implements Button.ClickListener {
    Property prop = null;
    Label viewer = null;
    TextField editor = null;
    CheckBox immediateCheckBox = null;

    @Override
    public void init() {
        Window mainWindow = new Window( "Propertyexperiment Application" );
        Label label = new Label( "Hello Vaadin user. The init() method ran: " + new java.util.Date().toString() );
        mainWindow.addComponent( label );
        
        //mainWindow.setImmediate( true ); // Does not help make the Viewer update after Editor edits.
        // Setting immediate on a Form affects the contained widgets, but not so on Window.

        String initTime = new java.util.Date().toString(); // Get the current datetime.
        prop = new ObjectProperty( initTime, String.class ); // Our data model. Initialize with current datetime.

        // Create a Label to view our Property.
        viewer = new Label(); // Component that implements com.vaadin.data Property.Viewer
        viewer.setCaption( "Property Viewer (Label):" );
        viewer.setPropertyDataSource( prop ); // Bind it to the data
        mainWindow.addComponent( viewer );

        // Create a TextField to edit our Property.
        editor = new TextField( "This string should NOT appear on screen. Will be replaced by Property Data Source." ); // Component that implements com.vaadin.data Property.Editor
        editor.setWidth( new java.util.Date().toString().length()*0.60f, Sizeable.UNITS_EM );
        editor.setCaption( "Property Editor (TextField):" );
        editor.setPropertyDataSource( prop ); // Bind the Property to the Editor.
        editor.setImmediate( true ); //  <==== This is the key to getting editor to update the Property immediately, and then the Viewer updates as well.
        //editor.setWriteThrough( true ); // True is the default.
        mainWindow.addComponent( editor );
        
        TextField ignoreTextField = new TextField("whatever");
        ignoreTextField.setCaption( "Ignore this field - here to accept focus:" );
        mainWindow.addComponent( ignoreTextField );
        
        immediateCheckBox = new CheckBox("Set 'immediate' mode on Property Editor");
        immediateCheckBox.setImmediate( true ); // Update the server-side state immediately.
        immediateCheckBox.setValue( new Boolean(true) );
        immediateCheckBox.addListener( this );
        mainWindow.addComponent( immediateCheckBox );

        setMainWindow( mainWindow );
    }
    
    public void buttonClick(Button.ClickEvent event) {
        CheckBox cb = (CheckBox)event.getSource();
        Boolean b = (Boolean)cb.getValue();
        editor.setImmediate( b );
        System.out.println("Info - Immediate mode on Property Editor (TextField) set to: " + b.toString() );
    }

}