在JavaScript中访问JSF嵌套复合组件元素

在JavaScript中访问JSF嵌套复合组件元素,jsf,jsf-2,icefaces,composite-component,Jsf,Jsf 2,Icefaces,Composite Component,我正在尝试使用复合组件来关闭JSF2项目中的弹出窗口 此代码库使用Icefaces 3.3.0(出于历史原因,其1.8.2兼容层)、Mojarra 2.2.7和Glassfish 4.1 我有一个input.xhtml,它提供了文本输入,并使用了一个2按钮弹出窗口(ok/cancel),这反过来又建立在基本弹出窗口的基础上 input.xhtml: <composite:interface> <!-- ... --> <composite:edita

我正在尝试使用复合组件来关闭JSF2项目中的弹出窗口

此代码库使用Icefaces 3.3.0(出于历史原因,其1.8.2兼容层)、Mojarra 2.2.7和Glassfish 4.1

我有一个input.xhtml,它提供了文本输入,并使用了一个2按钮弹出窗口(ok/cancel),这反过来又建立在基本弹出窗口的基础上

input.xhtml:

<composite:interface>
    <!-- ... -->
    <composite:editableValueHolder name="forInput" targets="theInput"/>
</composite:interface>
<composite:implementation>
    <my:popup2Buttons>
        <ice:inputText id="theInput" value="..."/>
        <script>setInputFocus("#{cc.clientId}:theInput");</script>
    </my:popup2Buttons>
</composite:implementation>         

setInputFocus(“#{cc.clientId}:输入”);
popup2buttons.xhtml:

<composite:interface>
    <!-- ... -->
</composite:interface>
<composite:implementation>
    <my:popup>
        <composite:insertChildren/>
        <ice:commandButton id="OkButton"
             value="Ok"
             actionListener="..."/>
        <ice:commandButton id="CancelButton"
              value="Cancel"
              actionListener="..."/>
    </my:popup>                    
</composite:implementation>

popup.xhtml:

<composite:interface>
    <!-- ... -->
</composite:interface>
<composite:implementation>
    <script>
    function setInputFocus(id) {
        document.getElementById(id).focus();
    }
    </script>

    <ice:panelPopup>
        <f:facet name="body">
            <h:panelGroup>
                <composite:insertChildren/>
            </h:panelGroup>
        </f:facet>
    </ice:panelPopup>
</composite:implementation>

函数setInputFocus(id){
document.getElementById(id.focus();
}
弹出窗口的工作原理与预期基本相同,即我可以输入一些内容,ok和cancel按钮可以工作,验证也可以工作

不起作用的是我的JavaScript代码,它试图在弹出窗口打开时集中输入

当我在Firebug中查看页面时,我看到输入的ID是
MyForm:j_idt63:j_idt64:j_idt67:theInput
,但是JavaScript代码试图将ID为
MyForm:j_idt63:theInput
的元素作为焦点

为什么
input.xhtml
中的
#{cc.clientId}
不是输入后来得到的正确ID?我需要做些什么才能让它工作

我已经看到了,但我不想要绑定,这样复合组件就可以独立于任何支持bean


这里还有什么我遗漏的吗?

复合组件是隐式的。即,他们在孩子的客户ID前加上自己的ID。这使得在同一视图中使用多个它们成为可能,而它们的子对象不会在生成的HTML输出中导致重复ID

在您的特定情况下,您将输入字段包装在另一个组合中,而该组合又包装在另一个组合中。如果您完全肯定在这个特定的组合中不需要多个命名容器相互包装,那么这些(
popup2buttons.xhtml
popup.xhtml
)可能不应该是复合的,而应该是
模板或
标记文件。另见

回到技术问题上来,这是因为
{cc.clientId}
没有引用嵌套复合组件的ID,而是引用当前复合组件的ID。因此,这将是关闭的。至于使用
绑定的潜在解决方案
,您找到的答案没有告诉您应该为此使用支持bean。答案中的
binding=“#{foo}”
代码保持原样。它确实是这样工作的,没有bean属性,请参见。但是,当您在同一视图中多次包含同一个组合,因此多个组件共享相同的
binding=“#{foo}”
时,此构造确实会失败。它确实不应该由多个组件共享,另请参见

要在没有支持bean的情况下解决这个问题,可以使用所谓的支持组件

com.example.InputComposite

@FacesComponent("inputComposite")
public class InputComposite extends UINamingContainer {

    private UIInput input;

    // +getter+setter.
}
input.xhtml

<cc:interface componentType="inputComposite">
    ...
</cc:interface>
<cc:implementation>
    ...
    <h:inputText binding="#{cc.input}" ... />
    <script>setInputFocus("#{cc.input.clientId}");</script>
    ...
</cc:implementation>

...
...
setInputFocus(“#{cc.input.clientId}”);
...

另一种方法是将它们重新加工成模板或标记文件。注意不要过度评价/过度使用复合材料。

绑定方法似乎只适用于输入,而不适用于
命令按钮等。这是正确的还是我遗漏了什么?当我向按钮添加
binding=“#{okButton}”
属性时,它不会被渲染。这不是原始问题的一部分;我尝试在输入上设置onKeyPress事件处理程序,并在用户按enter键时单击ok按钮,在用户按esc键时单击cancel按钮。如果多个按钮组件共享相同的
绑定
,则可能会发生这种情况。您应该使用
binding=“#{cc.okButton}”
,如答案中所述。