CompositeCell and hiding Cells Problem

398 views
Skip to first unread message

Ümit

unread,
Nov 5, 2010, 7:15:42 AM11/5/10
to Google Web Toolkit
I have an issue with the CompositeCell in a CellTable. My
CompositeCell consists of 3 ActionCells and a SelectionCell.
However the difference to a normal behaviour of a CompositeCell is
that I don't show all Cells at the same time but based on some state
in a domain object. Here is what I try to achieve:

Initial State
Second Stage After pressing on Save/Cancel
| NEW | -> (press on NEW ActionCell) -> | SELECTION SAVE CANCEL |
-> | NEW |

So after pressing on the NEW ActionCell it should be hidden and the
SelectionCell and the SAVE/CANCEL ActionCells should be shown. After I
press on SAVE or CANCEL again only the NEW ActionCell should be shown.

For the ActionCells i just override the render method of the Cell to
either not render the cell or to render it based on the state in my
domain object.
This looks like this:

public static class NewActioncell extends ActionCell<MyObject> {
public NewActioncell(String
text,com.google.gwt.cell.client.ActionCell.Delegate<MyObject>
delegate) {
super(text, delegate);
}

@Override
public void render(MyObject value, Object key, SafeHtmlBuilder sb)
{
if (value.getIsNew()) // get the state
super.render(value, key, sb);
}
}

The code for the Save and Cencel Action Cells is basically the same
apart from the fact that in the render method i will render the cells
if value.getIsNew() == false
The delegate action just sets the IsNew flag on the MyObject and calls
refresh on the DataProvider.

So far everything works as expected. As soon as I press on the NEW
Button, the NEW Button is hidden and only the CANCEL and SAVE buttons
are shown.

Now I also want to display a Select Box when SAVE and CANCEL are
shown. The Problem with the SelectionCell is that it is bound to
String as the Generic Type, so I can't access MyObject in its render
method.
My workaround is now to override the <X> void render method of the
CompositeCell and hide the SelectionCell there. This looks something
like that:

public static class CustomCompositeCell extends
CompositeCell<MyObject> {
public CustomCompositeCell(List<HasCell<MyObject, ?>> hasCells) {
super(hasCells);
}

@Override
protected <X> void render(MyObject value, Object
key,SafeHtmlBuilder sb, HasCell<MyObject, X> hasCell) {
if (!(hasCell.getCell() instanceof SelectionCell) ||
(value.getIsNew())) // check Cell and State
{
super.render(value, key, sb, hasCell);
}
}
}

So now the SelectionCell is displayed as soon as I press on the NEW
Button. However I get an exception in hosted and in production mode as
soon as I press on cancel or save.
The error is:

Chrome: com.google.gwt.core.client.JavaScriptException: (TypeError):
Cannot read property 'nextSibling' of null
Firefox: elem is null [Break on this error] var sib =
elem.nextSibling;

I managed to trace the problem back to the resetFocus method of the
CompositeCell class:

@Override
public boolean resetFocus(Element parent, C value, Object key) {
Element curChild =
getContainerElement(parent).getFirstChildElement();
for (HasCell<C, ?> hasCell : hasCells) {
// The first child that takes focus wins. Only one child should
ever be in
// edit mode, so this is safe.
if (resetFocusImpl(curChild, value, key, hasCell)) {
return true;
}
curChild = curChild.getNextSiblingElement();
}
return false;
}


It seems that the loop goes through all 4 Cells but one call of
getNextSiblingElement() returns null. The interesting part is that the
exception only happens when I add the selectionCell to CompositeCell.
It seems that not rendering an ActionCell by overriding its render
method doesn't cause a problem. However overriding the render method
of the CompositeCell to not render the SelectionCell causes this
Exception in the resetFocus method.

Is this a potential bug or is my approach of hiding Cells in a
CompositeCell flawed. Maybe there is a better approach.

Thanks in advance

Uemit

John LaBanca

unread,
Nov 5, 2010, 8:46:59 AM11/5/10
to google-we...@googlegroups.com
As far as the SelectionCell, we should have a version that is genericized and just use the selected index to map to the generic value.  In general, we probably also need an "EditCell", which is basically a two state cell that can enter and exit edit mode.  I'm sure that as people use the Cell Widgets, we'll figure out which Cells are missing from the API.

As for your immediate problem, I think the answer is that you need to override resetFocus() to do whatever you want.  Composite assumes that all four elements will be there, so if you override render to change that, then you need to override resetFocus() to handle the new structure.  Alternatively, you could render all four elements regardless of the state and just set the display to null.

Thanks,
John LaBanca
jlab...@google.com



--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.


Ümit

unread,
Nov 5, 2010, 11:24:39 AM11/5/10
to Google Web Toolkit
Thanks John for the quick response.

One question though. I am not sure what you mean with "setting the
display to null". I checked the specific classes (SelectionCell,
AbstractCell etc) but couldn't find anything which allows me to set
the display to null.
Maybe you can specify what you mean with display.

Thank in advance

Uemit






On Nov 5, 1:46 pm, John LaBanca <jlaba...@google.com> wrote:
> As far as the SelectionCell, we should have a version that is genericized
> and just use the selected index to map to the generic value.  In general, we
> probably also need an "EditCell", which is basically a two state cell that
> can enter and exit edit mode.  I'm sure that as people use the Cell Widgets,
> we'll figure out which Cells are missing from the API.
>
> As for your immediate problem, I think the answer is that you need to
> override resetFocus() to do whatever you want.  Composite assumes that all
> four elements will be there, so if you override render to change that, then
> you need to override resetFocus() to handle the new structure.
>  Alternatively, you could render all four elements regardless of the state
> and just set the display to null.
>
> Thanks,
> John LaBanca
> jlaba...@google.com
> > google-web-tool...@googlegroups.com<google-web-toolkit%2Bunsubs cr...@googlegroups.com>
> > .

John LaBanca

unread,
Nov 5, 2010, 12:03:29 PM11/5/10
to google-we...@googlegroups.com
Sorry, I was referring to the CSS property display, and I meant "none", not null.

Rendering the following will cause the span to be completely hidden and take up no space.
<span style=\"display:none;\">My cell content</span>

Thanks,
John LaBanca
jlab...@google.com


To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.

Ümit

unread,
Nov 5, 2010, 12:40:43 PM11/5/10
to Google Web Toolkit
Ah I see ;-)

However I somehow can't access the styles and the span respectively.
The render method of the SelectionCell renders the <select> tag
directly (I suppose the span is rendered by the CellTable itself).
I solved my problem by extending the SelectionCell and storing a
isVible Flag in it and then adding an additional span around it. The
class looks like this:

public class HideableSelectionCell extends SelectionCell{
protected boolean isVisible = true;

public HideableSelectionCell(List<String> options) {
super(options);
}

@Override
public void render(String value, Object key, SafeHtmlBuilder sb) {
if (!isVisible)
sb.appendHtmlConstant("<span style=\"display:none\">");
super.render(value, key, sb);

if (!isVisible)
sb.appendHtmlConstant("</span>");
}

public void setIsVisible(boolean isVisible) {
this.isVisible = isVisible;
}

public boolean getIsVisible(){
return this.isVisible;
}
}

And in the render method of the compositeCell I set the isVisible Flag
of the cell before rendering it.


Is that the right approach or is there some other way to access the
Cell Span's Style directly ?

Sorry for being so persistent ;-)

thanks

Uemit

On Nov 5, 5:03 pm, John LaBanca <jlaba...@google.com> wrote:
> Sorry, I was referring to the CSS property display, and I meant "none", not
> null.
>
> Rendering the following will cause the span to be completely hidden and take
> up no space.
> <span style=\"display:none;\">My cell content</span>
>
> Thanks,
> John LaBanca
> > > > google-web-tool...@googlegroups.com<google-web-toolkit%2Bunsubs cr...@googlegroups.com><google-web-toolkit%2Bunsubs

John LaBanca

unread,
Nov 5, 2010, 12:49:44 PM11/5/10
to google-we...@googlegroups.com
The default implementation of the render method in CompositeCell wraps each element in a span.  You could do the same and set the display style property based on the state, and then you don't need to extend SelectionCell.  While it isn't required for very simple Cells (that only render a single element), it makes sense to wrap each Cell in its own parent element.

Thanks,
John LaBanca
jlab...@google.com


To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages