GWT编辑器框架,带有简单的子编辑器和空字段

时间:2012-03-15 19:49:39

标签: gwt editor

UPDATE2:更新示例以演示原始问题。如果Person.address最初为null,则绑定失败。

我正在尝试使用一个非常简单的GWT编辑器框架示例与子编辑器一起工作。我在这里跟随伪示例http://code.google.com/webtoolkit/doc/latest/DevGuideUiEditors.html

当我调用driver.flush()时,如果原始Person.address为null,则Person.address的值始终为null - 无论我是否在地址的city字段中键入值。

这是我非常简单的POJO课程。

public class Person {

    private Address address;
    private String name;
    ... getters and setters
}

public class Address {

    private String city;
    ... getters and setters
}

现在是编辑。

public class PersonEditor extends DialogBox implements Editor<Person> {

    TextBox nameEditor = new TextBox();

    AddressEditor addressEditor = new AddressEditor();

    Button saveButton = new Button("Save");

    public PersonEditor() {
        VerticalPanel vp = new VerticalPanel();
        vp.add(nameEditor);
        vp.add(addressEditor);
        vp.add(saveButton);
        add(vp);
    }

    public HandlerRegistration addSaveClickHandler(ClickHandler handler) {
        return saveButton.addClickHandler(handler);
    }
}

地址编辑器不可能更简单。它只是一个TextBox

public class AddressEditor extends Composite implements Editor<Address> {

    TextBox cityEditor = new TextBox();

    public AddressEditor() {
        initWidget(cityEditor);
    }
}

和测试程序。如果取消注释p.setAddress,它将正常工作。

// Empty interface declaration, similar to UiBinder
interface Driver extends SimpleBeanEditorDriver<Person, PersonEditor> {
}

// Create the Driver
Driver driver = GWT.create(Driver.class);

@Override
public void onModuleLoad() {
    Person p = new Person();
    p.setName("Bob");

    Address a = new Address();
    a.setCity("Los Angeles");
    //p.setAddress(a);

    PersonEditor editor = new PersonEditor();
    editor.addSaveClickHandler(new ClickHandler() {
        @Override
        public void onClick(ClickEvent event) {
            Person edited = driver.flush();

            if (driver.hasErrors()) {
                GWT.log("Has errors");
                return;
            }
            GWT.log("Edited Name: " + edited.getName());
            GWT.log("Edited City: " + edited.getAddress().getCity());
        }
    });
    driver.initialize(editor);
    driver.edit(p);
    editor.center(); // show the dialog
}

当我点击保存时,无论我是否输入城市,都会抛出NPE。如果原始person对象具有一些非空地址,则绑定将以“两种”方式正常工作。

2 个答案:

答案 0 :(得分:0)

你是对的,它不会自动创建缺少的实例。在某些情况下,这可能是一项功能,尤其是在使用OptionalFieldEditor时。

一种想法是让你的模型的构造函数自动创建这些字段,或者当你在客户端上创建它们时,继续前进和下降,随时创建新实例。

如果这是一般性的需求,并且你觉得让自己的手变得有点脏,那么你可以使用一些想法 - 编辑器驱动程序将生成一个代理层次结构,可以使用{{1}访问}。这将允许您查看当前模型是什么,以及是否应该在继续之前初始化。 EditorDriver.accept(EditorVisitor)在这里提供了一些有用的方法,例如EditorContextsetInModel,问题将是如何构建这些项目,因为您发现它们丢失,以及何时将它们留空(Date,例如,字符串和盒装基元,但您有其他用例,您希望它们为空白)。我会为此创建一个getEditedType,其功能有点像RPC反序列化器,跟踪可能需要的构造函数,并将它们映射到Generator实例。

答案 1 :(得分:0)

感谢这是一个稍微陈旧的,但我也面临这个问题,最近开始玩编辑框架。

我发现实现所需功能的最简单方法是让你的地址“编辑器”实现LeafValueEditor。这要求您提供getValue()和setValue()的实现,当分别调用flush()和edit()时,驱动程序将调用它们。无论后备对象是否为空,都会发生这种情况。

我在下面提供了一个例子。我测试了它,它完美地工作。希望它也适合你!

public class AddressField extends Composite implements LeafValueEditor<AddressDTO> {

    interface Binder extends UiBinder<Widget, AddressField> {}
    private static Binder uiBinder = GWT.create(Binder.class);

    @UiConstructor
    public AddressField() {
        initWidget(uiBinder.createAndBindUi(this));
    }

    @UiField TextBox line1;
    @UiField TextBox line2;
    @UiField TextBox town;
    @UiField TextBox postcode;
    @UiField TextBox county;
    @UiField TextBox country;

    @Override
    public void setValue(AddressDTO value) {
        line1.setValue(value == null ? null : value.getLine1());
        line2.setValue(value == null ? null : value.getLine2());
        town.setValue(value == null ? null : value.getTown());
        postcode.setValue(value == null ? null : value.getPostcode());
        county.setValue(value == null ? null : value.getCounty());
        country.setValue(value == null ? null : value.getCountry());
    }

    @Override
    public AddressDTO getValue() {
        return new AddressDTO(line1.getValue(), line2.getValue(), postcode.getValue(), town.getValue(), county.getValue(), country.getValue());
    }
}