如何将 ClickableTextCell 渲染为 GWT CellTable 中的锚?
Posted
技术标签:
【中文标题】如何将 ClickableTextCell 渲染为 GWT CellTable 中的锚?【英文标题】:How can I render a ClickableTextCell as an anchor in a GWT CellTable? 【发布时间】:2011-06-09 04:09:53 【问题描述】:我在简单的 TextCell() 中有一个包含多列的 CellTable。其中两列是通过 ClickableTextCell() 类“可点击”的,但我想改变它们的外观。让单元格内容类似于锚标记,同时仍使用表格中的单元格的最简单方法是什么?
我尝试了以下方法: 1.实现自定义渲染器添加锚标签 2.搜索谷歌寻找提示 3. 忽略“我的库就可以了,你只需要改变你的整个框架”链接 4. 在他们的键盘上滚动我的头
有趣的是,这个简单的改变竟然如此令人讨厌。
我目前的想法是实现一个自定义的 AnchorCell 类型,它放入一个 Anchor 小部件而不是它在其他小部件中所做的任何事情,但我不确定需要做什么。
感谢任何帮助。
【问题讨论】:
【参考方案1】:首先 - 每个 GWT CellTable Column 只是一个 Cell(s) 堆栈,因为我们需要让每个 Cell 看起来像一个可以监听 Click 事件的锚点,让我们提供 ClickableTextCell 作为 Column 的参数。
Column<YourObj, String> col = new Column<YourObj, String>(new ClickableTextCell()) ;
第二个 - 在你的 Column 实例中覆盖“render()”方法并构建你想要的 html 模板,这里我们需要创建一个锚。
@Override
public void render(Context context, YourObj yourObj, SafeHtmlBuilder sb)
sb.appendHtmlConstant("<a style='text-decoration:underline; cursor: pointer;'>" + yourObj.getX() + "</a>");
3rd - 当我们使用 ClickableTextCell 时,它作为 Click 事件源。我们需要提供 ClickEvent 监听器,我们通过覆盖“onBrowserEvent()”方法来实现。
@Override
public void onBrowserEvent(Context context, Element elem, Customer customer, NativeEvent event)
if ("click".equals(event.getType()))
Window.alert("ID is : " + customer.getId());
完整代码sn-p:
Column<YourObj, String> col = new Column<YourObj, String>(new ClickableTextCell())
@Override
public String getValue(final YourObj yourObj)
return yourObj.getX();
@Override
public void render(Context context, YourObj yourObj, SafeHtmlBuilder sb)
sb.appendHtmlConstant("<a style='text-decoration:underline; cursor: pointer;'>" + yourObj.getX() + "</a>");
@Override
public void onBrowserEvent(Context context, Element elem, YourObj yourObj, NativeEvent event)
if ("click".equals(event.getType()))
Window.alert("ID is : " + yourObj.getId());
;
cellTable.addColumn(col, "First Name");
【讨论】:
【参考方案2】:使用appendHtmlConstant
本质上是一种黑客行为。简单地使用Anchor
中的toString
或其元素或传递HTML 字符串完全违反了SafeHtml
背后的概念。
在我看来,应该使用适当的SafeHtmlTemplates
来解决 HTML 的不可读和不安全的字符串连接问题。类似于:
protected interface AnchorTemplate extends SafeHtmlTemplates
@Template("<a href=\"0\">1</a>")
SafeHtml anchor(String url, String text);
然后您可以在其上使用GWT.create
并正确插入参数。
第二部分是可以优化读取小部件的 HTML 字符串。我正在扩展 AbstractCell
并有这个方法:
/* do not dare to copy - considered broken */
@Override
public void render(final Context context, final String value, final SafeHtmlBuilder sb)
final Anchor anchor = new Anchor();
anchor.setText(value);
sb.appendHtmlConstant(anchor.getElement().toString());
我刚刚经历了一个案例,锚单元在 superdev 模式下工作正常,但是编译它(可能使用更积极的优化设置)然后手动部署它会导致一个完全空的单元,在多个系统中没有可重复地更改代码.使用上述模板机制使其正常工作(GWT 2.7)。
【讨论】:
【参考方案3】:这实际上很简单,但令人惊讶的是,Google 上有多少错误和令人费解的答案,而似乎没有正确答案!无论如何,这是代码:
private Column<Object, SafeHtml> getAnchorColumn()
return new Column<Object, SafeHtml>(new SafeHtmlCell())
@Override
public SafeHtml getValue(final Object object)
Anchor anchor = new Anchor();
anchor.setHref(object.getURL());
anchor.setText(object.getText());
SafeHtmlBuilder sb = new SafeHtmlBuilder();
sb.appendHtmlConstant(anchor.toString());
return sb.toSafeHtml();
;
将对象更改为您要在表中呈现的任何对象,然后在创建列时运行此方法,简单!
【讨论】:
你会想要使用anchor.getElement().getString()
- 我已经用 a.toString()
提供了 javascript 调试输出【参考方案4】:
您的第一直觉(实现自定义渲染器)似乎要容易得多:
SafeHtmlRenderer<String> anchorRenderer = new AbstractSafeHtmlRenderer<String>()
@Override
public SafeHtml render(String object)
SafeHtmlBuilder sb = new SafeHtmlBuilder();
sb.appendHtmlConstant("<a href=\"javascript:;\">")
.appendEscaped(object).appendHtmlConstant("</a>");
return sb.toSafeHtml();
;
然后:
Column<YourThingy, String> anchorCol = new Column<YourThingy, String>(
new ClickableTextCell(anchorRenderer))
@Override
public String getValue(YourThingy object)
return object.toString();
;
【讨论】:
【参考方案5】:这是你需要的:
public class ClickableSafeHtmlCell extends AbstractCell<SafeHtml>
/**
* Construct a new ClickableSafeHtmlCell.
*/
public ClickableSafeHtmlCell()
super("click", "keydown");
@Override
public void onBrowserEvent(Context context, Element parent, SafeHtml value, NativeEvent event,
ValueUpdater<SafeHtml> valueUpdater)
super.onBrowserEvent(context, parent, value, event, valueUpdater);
if ("click".equals(event.getType()))
onEnterKeyDown(context, parent, value, event, valueUpdater);
@Override
protected void onEnterKeyDown(Context context, Element parent, SafeHtml value,
NativeEvent event, ValueUpdater<SafeHtml> valueUpdater)
if (valueUpdater != null)
valueUpdater.update(value);
@Override
public void render(Context context, SafeHtml value, SafeHtmlBuilder sb)
if (value != null)
sb.append(value);
然后用法:
Column<YourProxy, SafeHtml> nameColumn = new Column<YourProxy, SafeHtml>(
new ClickableSafeHtmlCell())
@Override
public SafeHtml getValue(YourProxy object)
SafeHtmlBuilder sb = new SafeHtmlBuilder();
sb.appendHtmlConstant("<a>");
sb.appendEscaped(object.getName());
sb.appendHtmlConstant("</a>");
return sb.toSafeHtml();
;
nameColumn.setFieldUpdater(new FieldUpdater<YourProxy, SafeHtml>()
@Override
public void update(int index, YourProxy object, SafeHtml value)
Window.alert("You have clicked: " + object.getName());
);
【讨论】:
如果没有 href 锚点,它在 Chrome 中仅显示为蓝色文本。 @thomas 建议的 "href='javascript:;'" 的 href 似乎有帮助。【参考方案6】:提到的解决方案有问题,这些是没有链接和样式表,a:hover 等不起作用。
这是我的解决方案:
private class SellerName
private final String sellerName;
private final Command cmd;
private SellerName(String displayName, Command cmd)
this.sellerName = displayName;
this.cmd = cmd;
public String getDisplayName()
return sellerName;
public Command getCommand()
return cmd;
;
private class SellerNameCell extends AbstractCell<SellerName>
public SellerNameCell()
super("click", "keydown");
@Override
public void render(com.google.gwt.cell.client.Cell.Context context, SellerName value, SafeHtmlBuilder sb)
if (value != null)
sb.appendHtmlConstant("<a href='javascript:;'>");
sb.appendEscaped(value.getDisplayName());
sb.appendHtmlConstant("</a>");
@Override
public void onBrowserEvent(Context context, Element parent, SellerName value, NativeEvent event, ValueUpdater<SellerName> valueUpdater)
if (value == null)
return;
super.onBrowserEvent(context, parent, value, event, valueUpdater);
if ("click".equals(event.getType()))
if (value.getCommand() != null)
value.getCommand().execute();
;
它创建了一个真正的可点击的锚单元:)
【讨论】:
哦,多么救命啊!【参考方案7】:举个例子:
public class MyClickableCellText extends ClickableTextCell
String style;
public MyClickableCellText()
super();
style = "myClickableCellTestStyle";
@Override
protected void render(Context context, SafeHtml value, SafeHtmlBuilder sb)
if (value != null)
sb.appendHtmlConstant("<div class=\""+style+"\">");
sb.append(value);
sb.appendHtmlConstant("</div>");
public void addStyleName(String style)
this.style = style;
还有样式(没有 div,因为您在上面硬编码样式):
.myClickableCellTestStyle
text-decoration:underline;
您甚至可以通过不扩展 ClickableTextCell 而是扩展 AbstractCell 来创建自己的单元格(更强大但需要更多解释)。需要的话就问我吧!
【讨论】:
我还没回过神来!看起来很有希望!谢谢! 点击动作在哪里?这似乎是一个不完整的答案。【参考方案8】:如果您查看 gwt 生成的 clickableTextCell html 代码,您会看到类似(取自 gwt 展示)的内容
<div style="outline:none;" tabindex="0">Click Robert</div>
所以我会建议你这样做:
ClickableTextCell cell = new ClickableTextCell();
cell.addStyleName("yourStyle");
在你的 style.css 中做任何你想做的事情。
.yourStyle div
text-decoration:underline;
【讨论】:
只有 ClickableTextCell 没有这个方法。 对不起,我不是说你可以直接使用它。您需要创建自己的 ClickableTextCell 实现。覆盖 onRender() 并执行 sb.append();s以上是关于如何将 ClickableTextCell 渲染为 GWT CellTable 中的锚?的主要内容,如果未能解决你的问题,请参考以下文章