在 Vaadin 7 中清除 FieldGroup

Clear a FieldGroup in Vaadin 7

如何清除 FieldGroup in a Vaadin 7 应用程序中的字段?

当我调用 FieldGroup::setItemDataSource and pass null, I get the text "null" appearing in TextField 由各种数据类型(数字,java.util.Date)支持的对象时。我可以理解将 "null" 显示为字符串表示形式的空值。但为什么那些 "null" 字符串默认不出现?默认情况下,我在所有字段中看到空的 TextField 字符串。

例如,考虑下面的示例应用程序。在下面的截图中我们:

  1. 启动应用程序。用户未采取任何操作。
    所有字段均为空白,无字符串,无 "null" 文本。
  2. 用户单击 "Show Bernard" 按钮。
  3. 用户单击 "Show No One" 按钮。此按钮调用 FieldGroup::setItemDataSource( null ),传递 null。
    数字和日期字段都显示 "null" 文本。为什么现在而不是在发布时?
    我怎样才能恢复到空白值?

应用启动

用户点击 "Show Bernard" 按钮

用户点击 "Show No One" 按钮

这是 Java 8 中完整的单文件 Vaadin 7.5.3 应用程序(使用 Lambda 语法)。

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
    {
    }

}

在点击任何按钮(初始状态)之前,这些行被执行:

TextField nameField = null;
//...
this.nameField = new TextField( "Name:" );

文档说:

public TextField(java.lang.String caption)

Constructs an empty TextField with given caption.

所以您的应用程序中的所有文本字段都是空值。但是......之后你使用:

this.fieldGroup.bind( this.nameField , "name" );

该值应该为空吗? [bind()](https://vaadin.com/api/com/vaadin/data/fieldgroup/FieldGroup.html#bind(com.vaadin.ui.Field, java.lang.Object)) 的文档再次说:

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).

所以必须用这个方法才能看到bind效果。

您问:但是为什么那些 "null" 字符串默认不出现?

我希望我的解释对您来说是清楚的,最初每个 TextField 都有 empty 值。而在调用bind()函数之后,它只在setItemDataSource(Item)之后影响视图,但是你在button的clickListener中调用这个函数要晚得多。所以最初很好,所有字段都有空值。

尝试添加 this.nameField.setNullRepresentation(""); 并在每个字段上调用相同的方法,根据 Book of Vaadin 它应该可以解决您的问题。