2015-10-26 72 views
1

我想在使用复合组件的JSF 2项目中干掉弹出窗口。在JavaScript中访问JSF嵌套复合组件元素

此代码库使用Icefaces 3.3.0(基于历史原因,它们的1.8.2兼容层),Mojarra 2.2.7和Glassfish 4.1。

我有input.xhtml它提供了一个文本输入,并使用一个2按钮弹出(确定/取消),它反过来建立在基本的弹出窗口。

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>   

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> 

弹出作品大多不如预期,即我可以进入的东西,ok和cancel按钮工作,并且验证也起作用。

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

当我查看Firebug中的页面时,发现输入的ID是MyForm:j_idt63:j_idt64:j_idt67:theInput,但JavaScript代码尝试集中ID为MyForm:j_idt63:theInput的元素。

为什么#{cc.clientId}input.xhtml不是输入结束后得到的正确ID?我需要做些什么来完成这项工作?

我见过BalusC's hint on adding a binding但我不想绑定,以便复合组件可以独立于任何后备bean。

有什么我在这里失踪?

回答

2

复合组件隐含为naming containers。即他们将他们的ID加到孩子的客户ID上。这使得可以在同一视图中使用它们中的多个,而不会导致其子代在生成的HTML输出中产生重复的ID。

在您的具体情况中,您将输入字段包裹在另一个组合中,而该组合又依次包裹另一个组合。如果您绝对肯定您不需要多个命名容器在这个特定组合中相互包装,那么那些(popup2buttons.xhtmlpopup.xhtml)可能不应该是组合,而是<ui:decorate>模板或<ui:composition>标记文件。请参见When to use <ui:include>, tag files, composite components and/or custom components?

回到技术问题,这是因为#{cc.clientId}未引用嵌套复合组件的ID,而是引用当前复合组件的ID。因此这将关闭。至于binding的潜在解决方案,您找到的答案无处告诉您应该为此使用辅助bean。答案中的binding="#{foo}"代码原样。它真的可以这样工作,没有bean属性,另见JSF component binding without bean property。但是,如果在同一视图中多次包含相同的合成并因此多个组件共享相同的binding="#{foo}",则此构造的确会失败。这确实是不应该由多个组件共享,也看到What is component binding in JSF? When it is preferred to be used?

为了解决这个问题,而不后台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> 

另一种方法是将它们返工到模板或标签文件。小心你不要高估/滥用复合材料。

+0

绑定方法似乎只适用于输入,但不适用于例如“CommandButton”。这是正确的还是我错过了什么?当我添加一个'binding =“#{okButton}”''属性到一个按钮时,它不会被渲染。这不是原始问题的一部分;我尝试在输入上使用onKeyPress事件处理程序,并在用户按下enter键时单击确定按钮,而在用户按下esc时单击取消按钮。 – Robert

+0

如果多个按钮组件共享相同的“绑定”,则可能发生这种情况。你应该按照答案中的解释使用'binding =“#{cc.okButton}”'。 – BalusC