如何将 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 中的锚?的主要内容,如果未能解决你的问题,请参考以下文章

如何将任何UIView渲染为UIImage [关闭]

如何将 Vue VNode 渲染为字符串

如何将渲染器指定为 SVG?

如何以编程方式将渲染设置为PrimeFaces列?

pythreejs:如何将剪裁的表面渲染为实体对象

React:如何将 JSON 对象转换为数组并渲染它?