CellTable - add Anchors to a cell

2,240 views
Skip to first unread message

Magnus

unread,
Aug 21, 2012, 8:43:10 PM8/21/12
to google-we...@googlegroups.com
Hi,

I am migrating a FlexTable to a CellTable. In the old table I have a column with actions that one can execute on the current row, e. g. "open, edit, delete".

The actions are HTML anchors with a clickHandler. In the old code I just put all anchors into a HorizontalPanel and put this into the table.

I tried to add such a panel into the CellTable by adding the result of Panel.toString to a SafeHtml.
However, the anchors appear, but nothing happens when you click one.

What can I do?

(I would like to have all anchors in a single cell.)

Thanks
Magnus




Magnus

unread,
Aug 22, 2012, 7:19:52 AM8/22/12
to google-we...@googlegroups.com
Hi,

I know how to add anchors to a cell using SafeHtml, but the clickHandler of the anchors is not triggered.

Below is how I create the anchors. How can I do that with CellTable?

Thanks
Magnus



  Column<MyData,SafeHtml> col_Action = new Column<MyData,SafeHtml>(new SafeHtmlCell())
  {
   @Override
   public SafeHtml getValue (MyData obj)
   {
    SafeHtmlBuilder sb = new SafeHtmlBuilder();
    Panel p = createActionPanel (obj);
    String t = p.toString ();
    sb.appendHtmlConstant (t);
    return sb.toSafeHtml();
   }
  };

 private Panel createActionPanel (MyData data)
 {
  HorizontalPanel p = new HorizontalPanel ();
  Anchor a;
 
  a = createAnchor ("Open","open",data.idx);
  p.add (a);

  a = createAnchor ("Edit","edit",data.idx);
  p.add (a);

  ...

  return (p);
 }
 
 private Anchor createAnchor (String label,String command,int idx)
 {
  Anchor a = new Anchor (label);
 
  a.addClickHandler(this);
  Element e = a.getElement();
 
  e.setAttribute("command",command);
  e.setAttribute("index",Integer.toString(idx));
 
  return (a);
 }

 @Override
 public void onClick(ClickEvent evt)
 {
  Window.alert("never called!");

  Object o = evt.getSource();
 
  if (o == null)
   return;
 
  if (!(o instanceof Anchor))
   return;

  Anchor a = (Anchor) o;
 
  int idx = Integer.parseInt(a.getElement().getAttribute("index"));
  String c = a.getElement().getAttribute("command");
 
  if (command.equals ("open"))
  {
   openMyData (idx);
  }
 }

Juan Pablo Gardella

unread,
Aug 22, 2012, 8:54:37 AM8/22/12
to google-we...@googlegroups.com
Hi, see  http://stackoverflow.com/questions/4691801/how-can-i-render-a-clickabletextcell-as-an-anchor-in-a-gwt-celltable

2012/8/22 Magnus <alpine...@googlemail.com>


--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-web-toolkit/-/NuD9scvbZqQJ.
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.

Magnus

unread,
Aug 22, 2012, 9:46:12 AM8/22/12
to google-we...@googlegroups.com
Hi Juan,

thank you.

These solutions do not have multiple anchors in one cell. Instead, the whole cell is made clickable...

I would like to put various anchors in one cell, i. e. I want *one* column that represents the actions one can take with a row (e. g. "open", "edit", "delete", and so on). The actions may be different for different records, so I want them to be in one column (to avoid many empty cells for most rows).

Can the solutions you pointed me to be used/modified for this purpose?

Magnus

Juan Pablo Gardella

unread,
Aug 22, 2012, 9:56:54 AM8/22/12
to google-we...@googlegroups.com
See CompositeCell and you can add multiple buttons that can appear like links. I attach a custom button that see like links. Add the files in the same package.

Juan

2012/8/22 Magnus <alpine...@googlemail.com>


Magnus

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
ButtonLink.css
ButtonLink.java

Magnus

unread,
Aug 22, 2012, 10:57:03 AM8/22/12
to google-we...@googlegroups.com
Hi Juan,

thank you for the infos and the code. I am still struggeling with it...

It seems that the composition of a CompositeCell is static. The examples I found all create an ArrayList<HasCell>l and then create an instance of CompositeCell with this list. Then, this instance is used to initialize the whole CellTable/CellList, e. g. here: http://ggwt.wordpress.com/2010/12/14/tutorial-eigene-compositecells-erstellen/#more-4

This means that all cells have the same subcells? What I need is to have differet subcells for different rows. I need to fill the composite cell differently for different rows.

I also wonder why we have to "simulate" hyperlinks with buttons that are made to look like hyperlinks. Why can't we just use Anchors? Are Anchors bad within a CellTable?

Magnus

Juan Pablo Gardella

unread,
Aug 22, 2012, 11:01:10 AM8/22/12
to google-we...@googlegroups.com
Anchors affect History. If you want to execute actions use buttons, if you want to use anchors for navigation, use it.

For dynamic cell table read http://stackoverflow.com/questions/7172262/create-gwt-celltable-dynamically.

I use it to have dynamic columns. Check perhaps you can use it for your requirements.

2012/8/22 Magnus <alpine...@googlemail.com>


Magnus

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.

Jens

unread,
Aug 22, 2012, 11:32:15 AM8/22/12
to google-we...@googlegroups.com

This means that all cells have the same subcells? What I need is to have differet subcells for different rows. I need to fill the composite cell differently for different rows.

I would just implement a custom cell that simply decides how to render itself based on the row value. If the row is editable add an edit link/button, if its not don't render it. Same with the other links/buttons you want to display. The cell would consume click events and in its event method you can figure out which link/button has been clicked and then start the action you need to start.
To render the cell differently the cell should know a SafeHtmlTemplate with methods that: a.) generate the basic cell structure and b.) generate your link/button.

This shouldn't be that hard to implement and it seems to be a lot cleaner than "misuse" CompositeCell somehow or extend GWT cells that don't really fit your needs and try to convince them to do what you want.

-- J.

Magnus

unread,
Aug 22, 2012, 12:49:51 PM8/22/12
to google-we...@googlegroups.com
Hi Jens,

this sounds really good, but I am totally new to this cellview technique and I need more precise hints at the moment:

- "implement a custom cell":
  from which class should it be derived? AbstractCell?

- "that simply decides":
  where and how can I implement this decision?

- "if the row is editable add an edit link/button"
  I already tried exactly this by adding a Panel of Anchor objects as SafeHtml,
  but the click handler is not triggered.
  I assume that the connection to the click handler gets lost when putting Panel.toString() into the SafeHtml

- "in its event method you can figure out which link/button has been clicked"
  How this is to be done should depend on how the links are created.
  Adding Anchors with click handlers did not work for me.

A basic skeleton would be fine...

Magnus

Jens

unread,
Aug 22, 2012, 1:26:46 PM8/22/12
to google-we...@googlegroups.com

this sounds really good, but I am totally new to this cellview technique

A simple tutorial for custom cells can be found at: https://developers.google.com/web-toolkit/doc/latest/DevGuideUiCustomCells
 
and I need more precise hints at the moment:

- "implement a custom cell":
  from which class should it be derived? AbstractCell?

As you cell does no editing, AbstractCell is the way to go.
 
- "that simply decides":
  where and how can I implement this decision?

Its implemented in the cell's render method. Inside the cell you have access to the row value and your row value will probably have methods like isEditable(), isDeletable(), etc. If it don't, you could provide a class to the cell that knows this information. With that information you can build up the HTML render string using SafeHtmlTemplates/SafeHtmlUtils.


- "if the row is editable add an edit link/button"
  I already tried exactly this by adding a Panel of Anchor objects as SafeHtml,
  but the click handler is not triggered.
  I assume that the connection to the click handler gets lost when putting Panel.toString() into the SafeHtml

Yes. You have only appended the HTML code of your widgets but events will be lost that way. Widget events only work inside a Widget hierarchy or when the widget provides a wrap(Element e) method like Button.wrap(buttonElement). 
Cell widget events work a bit different. For example if you have a cell that needs click events, the whole CellTable will consume native browser click events. Once a click happens the CellTable figures out which column/row is clicked and then calls the onBrowserEvent() method of the cell with that information. There is only one cell instance per column that is responsible to render all possible rows and to handle all events in that column for all rows. So it needs that context information to do its job.
 

- "in its event method you can figure out which link/button has been clicked"
  How this is to be done should depend on how the links are created.

While rendering your cell you would add custom attributes to your buttons/links that you can later identify when an event has occured. Something like <div data-action="edit">Edit</div> or <a href="javascript:;" data-action="delete">Delete</a>. You can then read the custom attribute to figure out which action to execute and you also know the column and row value. Should be everything you need.

Hope this helps. If you still need a skeleton implementation let me know.

-- J.

Magnus

unread,
Aug 23, 2012, 10:16:25 AM8/23/12
to google-we...@googlegroups.com
Hi Jens,

it works great now!

I derived a class GameCommandCell that represents the commands (as anchors) on a row, which is a game (as you know).

First, I was wondering which type I should pass to AbstractCell. I tried with SafeHtml, but then I had no access to the row data within onBrowserEvent. So I used AbstractCell<Game>:

    public class GameCommandCell extends AbstractCell<Game>

> Inside the cell you have access to the row value [...]

Well, I had a little bit trouble with the combination of types passed to the Column and the GameCommandCell. Whatever I did, they did not fit to each other, since Column.getValue delivers into Cell.render. I didn't want to use AbstractCell<Game>, because the cell does not represent a "game". But I found that using AbstractCell<Game> is the only way to have access to the row data within Cell.render. I also found that using IdentityColumn gives the cell access to the row:

    IdentityColumn<Game> col_Action = new IdentityColumn<Game>(new GameCommandCell ())

I am not finally happy with this. The cell should represent a set of commands, not a game. I think I will use an intermediate class "CommandSet" or something like that and use this as a type for AbstractCell, because this would be more generic and not restricted to the row type "Game".

> Hope this helps.

It did so! Thank you very much!

Magnus

-----

public class GameCommandCell extends AbstractCell<Game>
{
 public GameCommandCell ()
 {
  super ("click"); // we want click events
 }
 
 @Override
 public void render (Context context,Game value,SafeHtmlBuilder sb)
 {
  String t = renderCommand ("O","Open");
  sb.appendHtmlConstant(t);

  sb.appendHtmlConstant("&nbsp;");

  t = renderCommand ("E","Edit");
  sb.appendHtmlConstant(t);
 }
 
 public String renderCommand (String cmd,String lbl)
 {
  String t = "<a href='javascript:;' style='cursor: hand;' cmd='" + cmd + "'>" + lbl + "</a>";
 
  return (t);
 }

 @Override
 public void onBrowserEvent (Context context, Element parent,Game value,NativeEvent event, ValueUpdater<Game> valueUpdater)
 {
  super.onBrowserEvent(context, parent, value, event, valueUpdater);
 
  EventTarget tgt = event.getEventTarget();
  Element e = Element.as(tgt);
  String c = e.getAttribute("cmd");
  Window.alert("Command: " + c);
 }
}

Thomas Broyer

unread,
Aug 23, 2012, 10:27:31 AM8/23/12
to google-we...@googlegroups.com


On Thursday, August 23, 2012 4:16:25 PM UTC+2, Magnus wrote:
 @Override
 public void render (Context context,Game value,SafeHtmlBuilder sb)
 {
  String t = renderCommand ("O","Open");
  sb.appendHtmlConstant(t);

  sb.appendHtmlConstant("&nbsp;");

  t = renderCommand ("E","Edit");
  sb.appendHtmlConstant(t);
 }
 
 public String renderCommand (String cmd,String lbl)
 {
  String t = "<a href='javascript:;' style='cursor: hand;' cmd='" + cmd + "'>" + lbl + "</a>";
 
  return (t);
 }

 @Override
 public void onBrowserEvent (Context context, Element parent,Game value,NativeEvent event, ValueUpdater<Game> valueUpdater)
 {
  super.onBrowserEvent(context, parent, value, event, valueUpdater);
 
  EventTarget tgt = event.getEventTarget();
  Element e = Element.as(tgt);
  String c = e.getAttribute("cmd");
  Window.alert("Command: " + c);
 }
}

FYI, that'd be even easier (and possibly faster) with UiRenderer. Event handling would be much easier, unless you really need that "command identifier as a string" approach.

And as Juan Pablo said, you shouldn't use <a> for actions, use a <button> or a <span> and style it like a link if you wish, but do not abuse <a>.

Magnus

unread,
Aug 26, 2012, 9:00:38 AM8/26/12
to google-we...@googlegroups.com
Hi Thomas!


FYI, that'd be even easier (and possibly faster) with UiRenderer. Event handling would be much easier, unless you really need that "command identifier as a string" approach.

This is available in GWT 2.5 right? Until now I never thought about using release candidates and classes that are subject to change. Would it be a good idea to use GWT 2.5 RC now?

I use an enum now to represent these commands. But to attach them to a HTML tag the only way are attributes, and these are strings, or am I wrong?
 
And as Juan Pablo said, you shouldn't use <a> for actions, use a <button> or a <span> and style it like a link if you wish, but do not abuse <a>.

What's the problem with "<a>"?

Thanks
Magnus 

twoseven

unread,
Aug 26, 2012, 5:52:27 PM8/26/12
to google-we...@googlegroups.com
Here is some code for adding multiple anchors to cell with attribute as a command-

http://rowsandcolumns.blogspot.com/2012/08/gwt-celltable-add-multiple-anchors-to.html

It uses "<a> " tags for actions, maybe you can change to something else and style it.
Reply all
Reply to author
Forward
0 new messages