How does one clear the fields in a FieldGroup
in a Vaadin 7 app?
When I call FieldGroup::setItemDataSource
and pass null
, I get the text "null" appearing in TextField
objects backed by various data types (Number, java.util.Date). I can understand null values displaying "null" as a String representation. But why do those "null" strings not appear by default? By default I am seeing empty TextField strings in all fields.
For example, consider the example app below. In the following screenshots we:
FieldGroup::setItemDataSource( null )
, passing null.Here is the complete single-file Vaadin 7.5.3 app in Java 8 (using Lambda syntax).
package com.example.gridexample;
import javax.servlet.annotation.WebServlet;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.annotations.Widgetset;
import com.vaadin.data.fieldgroup.FieldGroup;
import com.vaadin.data.util.ObjectProperty;
import com.vaadin.data.util.PropertysetItem;
import com.vaadin.data.util.converter.StringToDateConverter;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
/**
*
*/
@Theme ( "mytheme" )
@Widgetset ( "com.example.gridexample.MyAppWidgetset" )
public class MyUI extends UI
{
PropertysetItem itemAaron = null;
PropertysetItem itemBernard = null;
TextField nameField = null;
TextField ageField = null;
TextField dateOfBirthField = null;
FieldGroup fieldGroup = null;
ZoneId zone = ZoneId.systemDefault(); // Or ZoneId.of( "America/Montreal" ) ;
@Override
protected void init ( VaadinRequest vaadinRequest ) {
final VerticalLayout layout = new VerticalLayout();
layout.setMargin( true );
layout.setSpacing( true );
setContent( layout );
Button buttonAaron = new Button( "Show Aaron" );
buttonAaron.addClickListener( ( ClickEvent event ) -> {
showAaron();
} );
layout.addComponent( buttonAaron );
Button buttonBernard = new Button( "Show Bernard" );
buttonBernard.addClickListener( ( ClickEvent event ) -> {
showBernard();
} );
layout.addComponent( buttonBernard );
Button buttonNoOne = new Button( "Show No One" );
buttonNoOne.addClickListener( ( ClickEvent event ) -> {
showNoOne();
} );
layout.addComponent( buttonNoOne );
this.itemAaron = new PropertysetItem();
this.itemAaron.addItemProperty( "name" , new ObjectProperty<>( "Aaron" ) );
this.itemAaron.addItemProperty( "age" , new ObjectProperty<>( 42 ) );
this.itemAaron.addItemProperty( "dateOfBirth" , new ObjectProperty<>( Date.from( ZonedDateTime.now( this.zone ).minusYears( 42 ).toInstant() ) ) );
this.itemBernard = new PropertysetItem();
this.itemBernard.addItemProperty( "name" , new ObjectProperty<>( "Bernard" ) );
this.itemBernard.addItemProperty( "age" , new ObjectProperty<>( 24 ) );
this.itemBernard.addItemProperty( "dateOfBirth" , new ObjectProperty<>( Date.from( ZonedDateTime.now( this.zone ).minusYears( 24 ).toInstant() ) ) );
this.nameField = new TextField( "Name:" );
this.ageField = new TextField( "Age:" );
this.dateOfBirthField = new TextField( "Date Of Birth:" );
// Customize the Converter assigned to our date-time field. A StringToDateConverter object is assigned by default.
//this.dateOfBirthField.setConverter( new StringToDateConverter() ); // Actually the default.
// this.dateOfBirthField.setConverter( new SpecialStringToDateConverter() );
layout.addComponent( this.nameField );
layout.addComponent( this.ageField );
layout.addComponent( this.dateOfBirthField );
this.fieldGroup = new FieldGroup();
this.fieldGroup.bind( this.nameField , "name" );
this.fieldGroup.bind( this.ageField , "age" );
this.fieldGroup.bind( this.dateOfBirthField , "dateOfBirth" );
this.fieldGroup.setReadOnly( true );
}
private void showAaron () {
this.fieldGroup.setItemDataSource( this.itemAaron );
}
private void showBernard () {
this.fieldGroup.setItemDataSource( this.itemBernard );
}
private void showNoOne () {
this.fieldGroup.setItemDataSource( null );
}
@WebServlet ( urlPatterns = "/*" , name = "MyUIServlet" , asyncSupported = true )
@VaadinServletConfiguration ( ui = MyUI.class , productionMode = false )
public static class MyUIServlet extends VaadinServlet
{
}
}
Before click at any button (initial state) those line are executed:
TextField nameField = null;
//...
this.nameField = new TextField( "Name:" );
Documentation says:
public TextField(java.lang.String caption)
Constructs an empty TextField with given caption.
So all textfields in your application has empty values. But... After that you use:
this.fieldGroup.bind( this.nameField , "name" );
Should the value be null? Again documentation for [bind()
](https://vaadin.com/api/com/vaadin/data/fieldgroup/FieldGroup.html#bind(com.vaadin.ui.Field, java.lang.Object)) says:
Binds the field with the given propertyId from the current item. If an item has not been set then the binding is postponed until the item is set using
setItemDataSource(Item)
.
So you must use this method to see bind
effects.
You asked: But why do those "null" strings not appear by default?
And I hope that my explanation is clear for you, that initially each TextField has empty value. And after call bind()
function, it affect view only after setItemDataSource(Item)
, but you call this function much later in button's clickListener. So initially it is fine, that all fields has empty values.