【问题标题】:How can I render a ClickableTextCell as an anchor in a GWT CellTable?如何将 ClickableTextCell 渲染为 GWT CellTable 中的锚?
【发布时间】:2011-06-09 04:09:53
【问题描述】:

我在简单的 TextCell() 中有一个包含多列的 CellTable。其中两列是通过 ClickableTextCell() 类“可点击”的,但我想改变它们的外观。让单元格内容类似于锚标记,同时仍使用表格中的单元格的最简单方法是什么?

我尝试了以下方法: 1.实现自定义渲染器添加锚标签 2.搜索谷歌寻找提示 3. 忽略“我的库就可以了,你只需要改变你的整个框架”链接 4. 在他们的键盘上滚动我的头

有趣的是,这个简单的改变竟然如此令人讨厌。

我目前的想法是实现一个自定义的 AnchorCell 类型,它放入一个 Anchor 小部件而不是它在其他小部件中所做的任何事情,但我不确定需要做什么。

感谢任何帮助。

【问题讨论】:

    标签: gwt anchor cell


    【解决方案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
          猜你喜欢
          • 2012-03-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-13
          • 1970-01-01
          • 1970-01-01
          • 2012-10-08
          • 2023-03-19
          相关资源
          最近更新 更多