繁体   English   中英

Tapestry Prototype通过区域更新中的ID选择元素

[英]Tapestry Prototype selecting element by ID on zone updates

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

我通过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

有没有办法使select的元素ID保持恒定,或者能够在每次区域更新时更改javascript和select的ID?

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

不论元素的内容如何,​​隐藏的输入字段每秒钟更改一次就会切换。 举例来说,如果我有GROUP_1GROUP_2GROUP_3Create New Group...GROUP_1初步选定,并改为GROUP_2 ,出现输入框。 当我将其更改为Create New Group... ,输入将再次隐藏。 同样,当我更改为GROUP_3 ,将出现输入字段。 请注意,在JSfiddle中,这很好用。 但是由于某种原因,它在我的Tapestry项目中不起作用。

EDIT2:好的,我尝试了一些修改:

Tapestry生成了id=groupSelecter_d769af562f89 select元素。 它还生成了插入此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控制台,并粘贴了刚剪切的相同代码。 而且,出于某些原因,它确实有效。 (即选择类)。

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

代替

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

您添加一个同名“ groupSelector”类

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

或者如果您有多个元素

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

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

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

如果要在ajax操作中使用clientId,这会有些棘手,因为只能在选择组件呈现后添加脚本。 在此之前,将不会定义clientId。 如果要执行此操作,建议从ajax操作返回RenderCommand 请注意,可以将Block 强制类型化为 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()
    );
}

我很惊讶Geek Num 88的添加类并按该类选择的想法不起作用。 您还可以添加data- *属性,然后选择该属性。

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

@InjectComponent
private Select groupSelector;

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

BTW。 解决此问题的挂毯方式是将脚本移动到js文件,并使用T5.extendInitializers(...),JavaScriptSupport.addInitializerCall(...)和@Import。 在这里演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM