【问题标题】:Tapestry Prototype selecting element by ID on zone updatesTapestry Prototype 在区域更新时按 ID 选择元素
【发布时间】:2013-11-25 09:40:20
【问题描述】:

我的页面上有一个包含选择元素的区域。

我正在通过 JavaScript 在该元素上添加一个 onChange 侦听器(感谢 http://jsfiddle.net/AnbmU/6/

void afterRender() {
    javaScriptSupport.addScript(
        "$('groupSelecter').observe('change', function() {" + 
        "    var width = $(this).getWidth();" + 
        "    var selectBox = $('groupSelecter');" + 
        "    var chosen = selectBox.selectedIndex >= 0 ? selectBox.options[selectBox.selectedIndex].innerHTML : undefined;" + 
        "    $(this).next('.ninja-input')" + 
        "         .toggleClassName('hidden', chosen != 'Create New Group...')" + 
        "         .select();" + 
        "});",
        ""
    );
}

当我触发区域刷新时出现问题,我的选择将 id 更改为如下内容:groupSelecter_846e54edd0b5

有没有办法让选择的元素 id 保持不变或能够在每次区域更新时更改 javascript 和选择的 id?

编辑: 另一个我以前不知道的问题。

隐藏的输入字段会在所选元素的第二次更改中切换一次,无论其内容如何。例如,如果我最初选择了GROUP_1GROUP_2GROUP_3Create New Group...GROUP_1,然后更改为GROUP_2,则会出现输入框。当我将其更改为Create New Group... 时,输入再次被隐藏。同样,当我更改为GROUP_3 时,会出现输入字段。请注意,在 JSfiddle 中,这很好用。但由于某种原因,它在我的 Tapestry 项目中不起作用。

编辑2: 好的,我尝试了更多的摆弄:

Tapestry 使用id=groupSelecter_d769af562f89 生成选择元素。 它还生成了插入这个 JavaScript(在 HTML 的底部):

$$('.groupSelecter').invoke('observe', 'change', function() {
    var width = $(this).getWidth();
    var chosen = $(this).selectedIndex >= 0 ? $(this).options[$(this).selectedIndex].innerHTML : undefined;
    $(this).next('.ninja-input')
        .toggleClassName('ninja-hidden', chosen != 'Create New Group...');
});

我在 Firefox 中检查了元素,导航到标签,找到生成的代码并将其删除。之后,我打开了 firefox JS 控制台并粘贴了我刚刚剪切的完全相同的代码。而且,瞧,它工作,出于某种原因。 (即类选择)。

【问题讨论】:

  • 显然,PrototypeJS 1.6.1.0 没有方法Element.toggleClassName(element, className[, bool]),而只有Element.toggleClassName(element, className),这导致了我在EDIT2 中的错误。

标签: java javascript prototypejs tapestry zone


【解决方案1】:

您需要确保每次呈现选择时触发 javascript。您目前仅在页面渲染时触发它(不是 ajax 更新)。

您可以在mixin 中执行此操作,也可以在页面呈现和 ajax 更新期间添加脚本。如果您使用类属性或数据属性(如该线程的其他答案中所建议的那样),您可以通过 JavaScriptSupport 在两个事件中添加脚本,因为在选择组件呈现之前该值是已知的。

如果您想在 ajax 操作中使用 clientId,这有点棘手,因为您只能在选择组件呈现后添加脚本。在此之前,将不会定义 clientId。如果您想这样做,我建议从您的 ajax 操作中返回 RenderCommand。注意Block可以是TypeCoerced到RenderCommand

例如:

@InjectComponent
private Zone zone;

@InjectComponent
private Select groupSelector;

@Inject
private TypeCoercer typeCoercer;

RenderCommand onActionFromSomeComponent() {
    return new RenderCommand() {
        public void render(MarkupWriter writer, RenderQueue queue) {
            RenderCommand zoneBody = typeCoercer.coerce(zone.getBody(), RenderCommand.class);
            zoneBody.render(writer, queue);
            javaScriptSupport.addScript(
                "$('%s').observe('change', function() {" + 
                   // more stuff
                 "});",
                 groupSelector.getClientId()
            );
        }
    };
}

void afterRender() {
    javaScriptSupport.addScript(
        "$('%s').observe('change', function() {" + 
            // more stuff
        "});",
        groupSelector.getClientId()
    );
}

【讨论】:

    【解决方案2】:

    我不知道 Tapestry,但如果它不改变你可以附加到一个类的类属性

    而不是

    $('groupSelecter').observe('change', function() {
    

    你添加了一个同名的类 'groupSelector'

    $$('.groupSelector').first().observe('change',function() {
    

    或者如果你有多个元素

    $$('.groupSelector').invoke('observe','change',function(){
    

    【讨论】:

      【解决方案3】:

      我很惊讶Geek Num 88 添加一个类并按该类进行选择的想法不起作用。您还可以添加一个 data-* 属性并通过它进行选择。

      否则,您可以观察动态的clientId。

      @InjectComponent
      private Select groupSelector;
      
      void afterRender() {
          javaScriptSupport.addScript(
              "$('%s').observe('change', function() {" + 
                  // more stuff
              "});",
          groupSelector.getClientId());
      }
      

      顺便说一句。解决此问题的挂毯方法是将脚本移动到 js 文件并使用 T5.extendInitializers(...)、JavaScriptSupport.addInitializerCall(...) 和 @Import。演示here

      【讨论】:

      • 最有趣的是,在 jsfiddle 上,它工作得很好,但在 Tapestry 中,就不太好。
      • 另外,我确实尝试使用groupSelector.getCliendID();,但无济于事。它不返回带后缀的生成 ID。
      • 您的afterRender() 方法在哪里?如果它在您的页面上,它只会在页面呈现时调用,而不是在 ajax 更新时调用。
      • 是的,我的Page.java 上有我的afterRender() 方法。
      • 因此,监听器仅在页面首次呈现时附加到选择。区域更新后,新的选择没有更改监听器。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-07
      相关资源
      最近更新 更多