If I look at dynatblerf sample, there is an AddressEditor in a
PersonEditor and it just seems to work.
I have the same thing, I have a SecuritySettingsEditor inside another
Editor and when I get the EntityProxy back, the security settings
field is always null. What does it take for the editor to generate
the value?
> --
> http://groups.google.com/group/Google-Web-Toolkit-Contributors
EditorContainer<OfficeHandle, HashSet<OfficeHandle>, OfficeEditor> offices;
which is a CompositeEditor
public class EditorContainer<T, C extends Collection<T>, E extends
Editor<T>> extends FlowPanel implements CompositeEditor<C, T, E>
I can set new up and place the HashSet<> manually inside the parent of
the office because it will get squashed the next time the editor is
flushed since EditorContainer gets setValue called with null
If you're using a composite, the idea is to set a non null container
value like so:
domainHandle = requests.create(DomainHandle.class);
r = requests.domainRequest().persist(getSessionId(), domainHandle);
driver = GWT.create(Driver.class);
driver.initialize(requests, view);
domainHandle = r.edit(domainHandle);
domainHandle.setOffices(new HashSet<OfficeHandle>()); // This
creates the empty set
domainHandle.setSecuritySettings(requests.create(SecuritySettingsHandle.class));
Then your composite will get called via the setValue method, this is
the set or list you newed up in your handle if you setup is OK
@Override
public void setValue(final C value) {
this.collection = value;
}
Then, when you're ready to flush, flush gets called, you just insert
whatever value you need in your collection
@Override
public void flush() {
for (int i = 0, j = editors.size(); i < j; i++) {
E subEditor = editors.get(i);
T value = chain.getValue(subEditor);
if (backing.get(i) != value)
backing.set(i, value);
collection.add(value);
public class ManagerSelector extends Composite implements
CompositeEditor<PersonProxy, PersonProxy, NameLabel>,
LeafValueEditor<PersonProxy> {
private EditorChain<PersonProxy, NameLabel> chain;
private NameLabel nameLabel = new NameLabel(new SimpleEventBus());
private PersonProxy manager;
public ManagerSelector() {
FlowPanel fp = new FlowPanel();
Button b = new Button("Choose randomly");
b.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
DynaTableRequestFactory rf = DynaTableRf.getRequestFactory();
int i = new Random().nextInt(100);
rf.schoolCalendarRequest().getPeople(i, 1).to(
new Receiver<List<PersonProxy>>() {
@Override
public void onSuccess(List<PersonProxy> response) {
assert response.size() == 1;
setValue(response.get(0));
}
}).fire();
}
});
fp.add(b);
fp.add(nameLabel);
initWidget(fp);
}
public void flush() {
}
public String getPathElement(NameLabel subEditor) {
return "";
}
public PersonProxy getValue() {
return manager;
}
public void onPropertyChange(String... paths) {
}
public void setDelegate(EditorDelegate<PersonProxy> delegate) {
}
public void setEditorChain(EditorChain<PersonProxy, NameLabel> chain) {
this.chain = chain;
}
public void setValue(PersonProxy value) {
this.manager = value;
if (manager != null) {
chain.attach(manager, nameLabel);
}
}
--
Bob Vawter
Google Web Toolkit Team
You have
> CompositeEditor<PersonProxy, PersonProxy, NameLabel>,
> LeafValueEditor<PersonProxy> {
But if the generic parameter was a collection, wouldn't the fact that
it's a leaf editor prevent the framework from entering sub-editors?
> --
> http://groups.google.com/group/Google-Web-Toolkit-Contributors
Hence the explicit chain.attach() call. If you wanted to edit an
optional list, you could replace the nameLabel with the ListEditor
adaptor class. Assuming that a PersonMight have a list of mentors:
// That's editor.client.adapters.ListEditor
MentorSelector implements LeafValueEditor<List<Person>>,
CompositeEditor<List<Person>, List<Person>, ListEditor<Person,
NameLabel>>
I don't suppose you have advice for using a mutable CellTable in the
editor framework?
> --
> http://groups.google.com/group/Google-Web-Toolkit-Contributors
I'm adding a new adapter class to handle this case, since optional
fields seems like a common thing to see and implementing it manually
requires a lot of boilerplate.
> I don't suppose you have advice for using a mutable CellTable in the
> editor framework?
Does the HasDataEditor adapter work for you?
I think it will see a lot of use.
>
>> I don't suppose you have advice for using a mutable CellTable in the
>> editor framework?
>
> Does the HasDataEditor adapter work for you?
>
It doesn't, because each row can be edited... but cell table doesn't
give you access to its rows, only a column format. Here, the editor
are actually the cells. So a button cell is a remove button. A edit
text cell is the number and a selection cell is the phone type.
I can just make a table but cell table added all this work to with
keyboard, mouse, blur, etc., events.
so
HandlerRegistration addRangeChangeHandler(RangeChangeEvent.Handler handler);
HandlerRegistration addRowCountChangeHandler(
RowCountChangeEvent.Handler handler);
aren't used. Because of that, it's not able to handle the scenarios
of the inline list that adds or remove items. In this case, a simple
list of phones. This list changes if we create a row and it also
changes if we hit the remove button on a row
This is intentional. HasDataEditor and its superclass, ListEditor
require that mutations of the structure of the list occur through the
wrapper retrieved from ListEditor.getList().
> --
> http://groups.google.com/group/Google-Web-Toolkit-Contributors
The FavoritesWidget in the DynaTableRf sample uses ListEditor. See
the uses of the displayedList field. It works this way so that
re-ordering operations on the list (like calling Collections.sort())
will keep both the backing data and the displayed list of editors in
sync.
I'm aware of this widget but I'm trying to use HasDataEditor with a
CellTable so it doesn't exactly translate 1:1
The HasDataEditorSource is indeed missing a call to setRowCount(). It
should check to see if the size of the exported list has changed
whenever create() or dispose() is called.
I hit a bug in public
SimpleEntityProxyId.equals
boolean equals(Object o) {
if (!(o instanceof SimpleEntityProxyId<?>)) {
return false;
}
SimpleEntityProxyId<?> other = (SimpleEntityProxyId<?>) o;
if (!proxyClass.equals(other.proxyClass)) {
return false;
}
return (clientId != NEVER_EPHEMERAL && clientId == other.clientId)
|| serverId.equals(other.serverId);
}
both entities here were created locally.
So here I'll have clientId == 12 and other.clientId == 13 for example.
So that part is OK but then it goes into the ||
serverId here is null because it never got into the server, so it throws an NPE.
PhoneHandle handle1 = rc.create(PhoneHandle.class);
PhoneHandle handle2 = rc.create(PhoneHandle.class);
assert !handle1.equals(handle2);
throws because serverId is null in SimpleEntityProxyId