Как вы делаете вложенные редакторы в GWT2? - PullRequest
0 голосов
/ 20 февраля 2012

Не могли бы вы дать мне рабочий пример вложенных редакторов?Я прочитал этот документ, но он мне не помог.В моем коде у меня есть класс Person и Organization .

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>

Он прекрасно работает.

Вот редактор для Organization:

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 ]

1 голос
/ 20 февраля 2012
 <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 (и нет смысла делать его одним). Так что просто добавьте ваш PersonEditor в ui.xml OrganizationEditor как обычный виджет.

Например:

<!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;
0 голосов
/ 21 февраля 2012

Ах ... Я должен создать прокси для 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);
    }
}
...