在JavaScript中访问JSF嵌套的复合组件元素 [英] Accessing JSF nested composite component elements in JavaScript

查看:157
本文介绍了在JavaScript中访问JSF嵌套的复合组件元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用复合组件干燥JSF 2项目中的弹出窗口.

I am trying to DRY up popup windows in my JSF 2 project using composite components.

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

This code base uses Icefaces 3.3.0 (with their 1.8.2 compatibility layer for historical reasons), Mojarra 2.2.7, and Glassfish 4.1.

我有input.xhtml,它提供文本输入并使用2按钮弹出窗口(确定/取消),而该按钮又基于基本弹出窗口.

I have input.xhtml which provides a text input and uses a 2-button popup (ok/cancel), which in turn builds on the basic popup.

input.xhtml:

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:

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:

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>

弹出窗口的工作原理大致符合预期,即,我可以输入内容,确定和取消按钮起作用,并且验证也起作用.

The popup works mostly as expected, i.e., I can enter something, the ok and cancel buttons work, and validation works as well.

不起作用的是我的JavaScript代码,该代码尝试在弹出窗口打开时集中输入内容.

What does not work is my JavaScript code that tries to focus the input when the popup opens.

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

When I look at the page in Firebug, I see that the input's ID is MyForm:j_idt63:j_idt64:j_idt67:theInput, but the JavaScript code tries to focus an element with the ID MyForm:j_idt63:theInput.

为什么input.xhtml中的#{cc.clientId}不是输入最终得到的正确ID,以后才能获取?我需要做些什么才能使它起作用?

Why is #{cc.clientId} in input.xhtml not the correct ID that the input ends up getting later? What do I need to do to make this work?

我已经看到 BalusC关于添加绑定的提示,但我不想绑定,这样复合组件可以独立于任何支持bean.

I've seen BalusC's hint on adding a binding but I don't want a binding so that the composite component can be independent of any backing beans.

这里还有我想念的东西吗?

Is there something else I am missing here?

推荐答案

复合组件隐式地

Composite components are implicitly naming containers. I.e. they prepend their ID to the client ID of the children. This makes it possible to use multiple of them in the same view without their children causing duplicate IDs in generated HTML output.

在您的特定情况下,您将输入字段包装在另一个组合中,该组合又又包装在另一个组合中.如果您完全肯定不需要在此特定组成中相互包裹的多个命名容器,则那些(popup2buttons.xhtmlpopup.xhtml)可能不应该是复合的,而应该是<ui:decorate>模板或<ui:composition>标记文件.另请参见何时使用< ui :include> ;、标记文件,复合组件和/或自定义组件?

In your specific case, you wrapped the input field in another composite which is in turn wrapped in again another composite. If you're absolutely positive that you don't need multiple naming containers wrapping in each other in this specific composition, then those (popup2buttons.xhtml and popup.xhtml) probably shouldn't be composites, but rather <ui:decorate> templates or <ui:composition> tagfiles. See also When to use <ui:include>, tag files, composite components and/or custom components?

回到技术问题,是由于#{cc.clientId}并不引用嵌套的复合组件的ID,而是当前复合组件的ID.因此,这将关闭.对于binding的潜在解决方案,您找到的答案无处不表明您应为此使用备用Bean.答案中的binding="#{foo}"代码保持原样.如果没有bean属性,它确实可以通过这种方式工作,另请参见没有bean属性的JSF组件绑定.但是,当您在同一视图中多次包含相同的合成,因此多个组件共享相同的binding="#{foo}"时,此构造确实会失败.实际上,不应由多个组件共享它,另请参见

Coming back to the technical problem, it's caused because the #{cc.clientId} does not refer the ID of the nested composite component, but of the current composite component. And thus this would be off. As to the potential solution with binding, the answer which you found does nowhere tell that you should use a backing bean for this. The binding="#{foo}" code in the answer was as-is. It really works that way, without a bean property, see also JSF component binding without bean property. However, this construct would indeed fail when you include the same composite multiple times in the same view and thus multiple components share the same binding="#{foo}". It indeed isn't supposed to be shared by multiple components, see also What is component binding in JSF? When it is preferred to be used?

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

To solve this without a backing bean, you can use a so-called backing component.

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>

另一种方法是将它们重新加工为模板或标记文件.请注意,不要高估/过度使用复合材料.

The alternative is to rework them into templates or tagfiles. Be careful that you don't overvalue/overuse composites.

这篇关于在JavaScript中访问JSF嵌套的复合组件元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆