如何在 GWT2 中进行嵌套编辑器?
您能给我嵌套编辑器的工作示例吗?我已阅读此文档,但它对我没有帮助。在我的代码中,我有类 Person 和 Organization 。
Organization
具有 Person
类型的字段 contactPerson
。
所以我为 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)不会自动刷新?它应该发生吗?正确的解决方案是什么?
Сould you please give me working example of nested editors ? I've read this document but it didn't help me. In my code I have class Person and Organization.
Organization
has field contactPerson
of a type Person
.
So I created following editor for 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));
}
}
its corresponding .ui.xml is
<!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>
It works nicely.
Here is editor for 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));
}
}
and its corresponding .ui.xml is
<!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>
interface for proxy of Organization is
@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);
}
and finally here is class that uses all described above
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())
{
}
}
}
The question is why nested editor (PersonEditor) doesn't get flushed automatically ? Is it supposed to happen ? What is the proper solution ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这段代码抛出异常。
之后是 ValueBox 的子类型(例如 TextBox、DoubleBox,...)。您的 PersonEditor 不是 ValueBox(将其设为 ValueBox 是没有意义的)。因此,只需将您的 PersonEditor 添加到 OrganizationEditor 的 ui.xml 中,就像普通的 Widget 一样。例如:
在Java类中,更改
为
This code throws the exception. After
<e:valuebox>
a sub-type of a ValueBox is expected (e.g. TextBox, DoubleBox,...). Your PersonEditor is not a ValueBox (and it makes no sense to make it one). So just add your PersonEditor in the OrganizationEditor'sui.xml
like a normal Widget.For example:
In the Java class, change
to
啊...我必须手动为
contactPerson
创建代理!Ah... I have to create proxy for
contactPerson
manually!