JSF复合组件*PrimeFaces

3

当widgetVar的名称是动态生成的时,我在使用中遇到了问题。我们应该如何正确地调用这样的小部件?组件的代码:

<cc:attribute name="id" required="true" type="java.lang.String" />
...
<cc:implementation>
    <p:selectOneRadio widgetVar="widgetVariable#{cc.attrs.id}" id="#{cc.attrs.id}" required="false" immediate="#{cc.attrs.immediate}"
                      value="#{cc.attrs.value}">
        <p:ajax event="click" oncomplete="checkRadio()"/>
        <cc:insertChildren/>
    </p:selectOneRadio>

    <script type="text/javascript">
        /*  <![CDATA[ */

        function checkRadio() {
            var widgetVariable = widgetVariable#{cc.attrs.id}; //HERE PROBLEM
            widgetVariable.dosmth();
        }

        /*    ]]> */
    </script>
</cc:implementation>  

很奇怪,它能够工作,但是当我在页面上使用多个该组件实例时,widgetwar有时会变得混乱,并且为许多组件实例生成javascript。

编辑:一切正常。 无论如何,我有一个新问题。我在这个.js文件中创建了一些全局状态变量。

var state = -1;

function checkRadio() {
        var widgetVariable = widgetVariable#{cc.attrs.id}; //HERE PROBLEM
        widgetVariable.dosmth(state);
}

但每个状态应该只针对一个组合实例,目前每个组合都使用这个变量,有什么想法吗?


id长什么样?它包含哪些字符? - user1983983
任何,一些字母/数字“myComponent”、“something2”等。 - user2771738
只有字母和数字字符,没有特殊字符吗? - user1983983
是的,我正在测试 Balus 解决方案,马上回来。 - user2771738
1个回答

2

实际上有两个问题。

第一个问题是您在XHTML文件中声明JS函数而不是真正的JS文件。如果您有多个这些组件,那么您基本上会在HTML输出中生成多个JS函数checkRadio()。在浏览器中查看页面,右键单击并选择查看源代码。您将基本上看到:

<script type="text/javascript">
    function checkRadio() {
        // ...
    }
</script>
<script type="text/javascript">
    function checkRadio() {
        // ...
    }
</script>
<script type="text/javascript">
    function checkRadio() {
        // ...
    }
</script>
...

他们会互相覆盖,直到最后一个。因此,当调用checkRadio()时,实际上将调用最后一个函数。这显然是不正确的。
您应该只有一个函数。您可以通过将其作为函数参数来使变量外部化。更重要的是,您不应该在XHTML文件中编写JS代码,而是应该在独立的JS文件中编写,然后通过<h:outputScript>进行包含。额外的好处是,即使您拥有多个组合组件,它也会自动确保仅加载一个JS文件。
<cc:implementation>
    <h:outputScript name="myComposite.js" />
    ...
    <p:ajax event="click" oncomplete="checkRadio('#{cc.attrs.id}')" />
</cc:implementation>

回到您的具体问题,您的第二个问题,您可以利用window[variableName]符号来通过动态组合的变量名称获取全局(window)变量。因此,在您的myComposite.js中的checkRadio()函数(无论您想将其命名为什么,但与myComposite.xhtml相同的文件名最能自我说明)应该如下所示:

function checkRadio(compositeId) {
   var widgetVariableName = "widgetVariable" + compositeId;
   var widgetVariable = window[widgetVariableName];
   widgetVariable.dosmth();
}

1
与所有其他JSF资源相同的位置。在/resources文件夹中。如果您希望它与组合XHTML位于同一文件夹中,只需根据实际的/resources相对路径相应地修改<h:outputScript library>即可。顺便说一句,“js”绝对是一个糟糕的库名称。另请参见https://dev59.com/e2ct5IYBdhLWcg3wk-Rq。 - BalusC
只需将其作为另一个函数参数传递? - BalusC
我没有看到将其作为另一个函数参数传递会形成问题。 - BalusC
我认为我们谈论的是两件不同的事情。我有问题为每个组件的状态动态创建变量,因为我只有一个状态变量,即使该变量状态在自己的文件中,它仍然包含在页面上所有组件的JavaScript中。 - user2771738
好的,问题已经解决。我之前并不知道在JS中不需要声明全局变量,因此我将每个状态都替换为: window[stateName],其中stateName = "state" + compositeId(compositeId来自函数参数)。 - user2771738
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接