你如何在GWT2中嵌套编辑器?

时间:2012-02-20 06:53:36

标签: gwt gwt2 gwt-editors

你能不能给我一些嵌套编辑器的例子?我已经阅读了this文件,但它对我没有帮助。在我的代码中,我有类组织

Organization包含contactPerson类型的字段Person

所以我为Person创建了以下编辑器:

public class PersonEditor extends Composite implements Editor<PersonProxy>
{
    interface PersonEditorUiBinder extends UiBinder<Widget, PersonEditor>
    {
    }

    private static PersonEditorUiBinder uiBinder = GWT.create(PersonEditorUiBinder.class);

    @UiField
    ValueBoxEditorDecorator<String> name;
    @UiField
    ValueBoxEditorDecorator<String> phoneNumber;
    @UiField
    ValueBoxEditorDecorator<String> email;

    @UiField
    CaptionPanel captionPanel;

    public void setCaptionText(String captionText)
    {
        captionPanel.setCaptionText(captionText);
    }

    public PersonEditor()
    {
        initWidget(uiBinder.createAndBindUi(this));
    }
}

其对应的.ui.xml是

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
             xmlns:g='urn:import:com.google.gwt.user.client.ui'
             xmlns:e='urn:import:com.google.gwt.editor.ui.client'

             ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
             ui:generateKeys="com.google.gwt.i18n.server.keygen.MD5KeyGenerator"
             ui:generateLocales="en,ru">
    <ui:style src="../common.css"/>
    <g:CaptionPanel captionText="Test" ui:field="captionPanel">
        <g:HTMLPanel>
            <table class="{style.forform}">
                <tr>
                    <th class="{style.forform}">
                        <div>
                            <ui:msg meaning="person's name">Name:</ui:msg>
                        </div>
                    </th>
                    <td class="{style.forform}">
                        <e:ValueBoxEditorDecorator ui:field="name" stylePrimaryName="{style.forform}">
                            <e:valuebox>
                                <g:TextBox stylePrimaryName="{style.forform}"/>
                            </e:valuebox>
                        </e:ValueBoxEditorDecorator>
                    </td>
                </tr>
                <tr>
                    <th class="{style.forform}">
                        <div>
                            <ui:msg>Phone Number:</ui:msg>
                        </div>
                    </th>
                    <td class="{style.forform}">
                        <e:ValueBoxEditorDecorator ui:field="phoneNumber" stylePrimaryName="{style.forform}">
                            <e:valuebox>
                                <g:TextBox width="100%" stylePrimaryName="{style.forform}"/>
                            </e:valuebox>
                        </e:ValueBoxEditorDecorator>
                    </td>
                </tr>
                <tr>
                    <th class="{style.forform}">
                        <div>
                            <ui:msg>EMail:</ui:msg>
                        </div>
                    </th>
                    <td class="{style.forform}">
                        <e:ValueBoxEditorDecorator ui:field="email" stylePrimaryName="{style.forform}">
                            <e:valuebox>
                                <g:TextBox width="100%" stylePrimaryName="{style.forform}"/>
                            </e:valuebox>
                        </e:ValueBoxEditorDecorator>
                    </td>
                </tr>
            </table>
        </g:HTMLPanel>
    </g:CaptionPanel>
</ui:UiBinder>

效果很好。

这是组织编辑:

public class OrganizationEditor extends Composite implements Editor<OrganizationProxy>
{
    interface OrganizationEditorUiBinder extends UiBinder<Widget, OrganizationEditor>
    {
    }

    private static OrganizationEditorUiBinder uiBinder = GWT.create(OrganizationEditorUiBinder.class);

    @UiField
    CaptionPanel captionPanel;

    @UiField
    ValueBoxEditorDecorator<String> name;

    @UiField
    ValueBoxEditorDecorator<String> address;

    @UiField
    PersonEditor personEditor;

    public void setCaptionText(String captionText)
    {
        captionPanel.setCaptionText(captionText);
    }

    public OrganizationEditor()
    {
        initWidget(uiBinder.createAndBindUi(this));
    }
}

及其对应的.ui.xml是

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
             xmlns:g='urn:import:com.google.gwt.user.client.ui'
             xmlns:e='urn:import:com.google.gwt.editor.ui.client'
             xmlns:c='urn:import:com.zasutki.courierApp.client.customer'
             xmlns:myui='urn:import:com.zasutki.courierApp.client.ui'

             ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
             ui:generateKeys="com.google.gwt.i18n.server.keygen.MD5KeyGenerator"
             ui:generateLocales="en,ru">
    <ui:style src="../common.css"/>
    <g:CaptionPanel ui:field="captionPanel">
        <myui:VerticalFlowPanel>
            <g:HTMLPanel>
                <table class="{style.forform}">
                    <tr>
                        <th class="{style.forform}">
                            <div>
                                <ui:msg meaning="Name of organization">Name:</ui:msg>
                            </div>
                        </th>
                        <td class="{style.forform}">
                            <e:ValueBoxEditorDecorator ui:field="name" stylePrimaryName="{style.forform}">
                                <e:valuebox>
                                    <g:TextBox stylePrimaryName="{style.forform}"/>
                                </e:valuebox>
                            </e:ValueBoxEditorDecorator>
                        </td>
                    </tr>
                    <tr>
                        <th class="{style.forform}">
                            <div>
                                <ui:msg>Address:</ui:msg>
                            </div>
                        </th>
                        <td class="{style.forform}">
                            <e:ValueBoxEditorDecorator ui:field="address" stylePrimaryName="{style.forform}">
                                <e:valuebox>
                                    <g:TextBox stylePrimaryName="{style.forform}"/>
                                </e:valuebox>
                            </e:ValueBoxEditorDecorator>
                        </td>
                    </tr>
                </table>
                <c:PersonEditor ui:field="personEditor" captionText="Contact person">
                    <ui:attribute name="captionText"/>
                </c:PersonEditor>
            </g:HTMLPanel>
        </myui:VerticalFlowPanel>
    </g:CaptionPanel>
</ui:UiBinder>

组织代理的接口是

@ProxyFor(value = Organization.class, locator = ObjectifyLocator.class)
public interface OrganizationProxy extends EntityProxy
{
    public String getName();
    public void setName(String name);
    public String getAddress();
    public void setAddress(String address);
    public PersonProxy getContactPerson();
    public void setContactPerson(PersonProxy contactPerson);
}

最后这里是使用上述所有内容的类

public class NewOrderView extends Composite
{
    interface Binder extends UiBinder<Widget, NewOrderView>
    {
    }

    private static Binder uiBinder = GWT.create(Binder.class);

    // Empty interface declaration, similar to UiBinder
    interface OrganizationDriver extends SimpleBeanEditorDriver<OrganizationProxy, OrganizationEditor>
    {
    }

    OrganizationDriver driver = GWT.create(OrganizationDriver.class);

    @UiField
    Button save;

    @UiField
    OrganizationEditor orgEditor;

    OrganizationProxy organizationProxy;

    public NewOrderView()
    {
        initWidget(uiBinder.createAndBindUi(this));

        organizationProxy = createFactory().contextOrder().create(OrganizationProxy.class);

        // Initialize the driver with the top-level editor
        driver.initialize(orgEditor);

        // Copy the data in the object into the UI
        driver.edit(organizationProxy);
    }

    @UiHandler("save")
    void buttonClick(ClickEvent e)
    {
        e.stopPropagation();

        OrganizationProxy edited = driver.flush();
        PersonProxy person = edited.getContactPerson();
        // person is always null !!!
        if (driver.hasErrors())
        {
        }
    }
}

问题是为什么嵌套编辑器(PersonEditor)不会自动刷新?这应该发生吗?什么是正确的解决方案?

2 个答案:

答案 0 :(得分:1)

 <e:ValueBoxEditorDecorator ui:field="contactPerson">
                    <e:valuebox>
                        <c:PersonEditor captionText="Contact person">
                            <ui:attribute name="captionText"/>
                        </c:PersonEditor>
                    </e:valuebox>
                </e:ValueBoxEditorDecorator>

此代码抛出异常。在<e:valuebox>之后,期望ValueBox的子类型(例如TextBox,DoubleBox,...)。你的PersonEditor不是一个ValueBox(并且它是没有意义的)。所以只需在OrganizationEditor的ui.xml中添加PersonEditor,就像普通的Widget一样。

例如:

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
    ....>
    <ui:style src="../common.css"/>
    <g:CaptionPanel ui:field="captionPanel">
        <myui:VerticalFlowPanel>
            <g:HTMLPanel>
                <table class="{style.forform}">
            // your other input fields
                </table>
            </g:HTMLPanel>

            // Add the PersonEditor to the FlowPanel
           <c:PersonEditor captionText="Contact person">
                <ui:attribute name="captionText"/>
           </c:PersonEditor>
            </myui:VerticalFlowPanel>
        </g:CaptionPanel>
    </ui:UiBinder>

在Java类中,更改

@UiField
    ValueBoxEditorDecorator<PersonEditor> contactPerson;

@UiField
    PersonEditor contactPerson;

答案 1 :(得分:0)

啊......我必须手动为contactPerson创建代理!

public class NewOrderView extends Composite
{
    public NewOrderView()
    {
        initWidget(uiBinder.createAndBindUi(this));

        AdminRequestFactory.OrderRequestContext orderRequestContext = createFactory().contextOrder();
        organizationProxy = orderRequestContext.create(OrganizationProxy.class);
        organizationProxy.setContactPerson(orderRequestContext.create(PersonProxy.class));

        // Initialize the driver with the top-level editor
        driver.initialize(orgEditor);

        // Copy the data in the object into the UI
        driver.edit(organizationProxy);
    }
}