当包含JS代码的复合组件被多次呈现时,JS仅适用于最后一个组件

时间:2013-04-05 04:36:53

标签: jquery jsf jsf-2 primefaces composite-component

我有一个使用PrimeFaces <p:selectOneMenu>的复合组件,如:

<p:selectOneMenu id="inOut" onchange="inOutChanged()">
  ..
</p:selectOneMenu>

然后我有一个JavaScript文件,作为定义该组件的组件的一部分 inOutChanged()功能类似于

function inOutChanged() {
  var inOut = $({cc.clientId}:inOut);
  if(inOut.val() == "INC") {
    slider.addClass("includedInRange");
  }
}

当页面上只有一个组合时,此组合组件可以正常工作。问题是我需要在页面上有4个。因此,当我更改一个复合组件的选择时,它将更改最后一个组件的滑块类。我相信这是因为实际上有4个inOutChanged()函数都在页面中定义。

有没有办法对函数进行范围调整或将其命名为唯一的,以便它们不会相互踩踏?

2 个答案:

答案 0 :(得分:2)

您的具体问题是由于您在全局范围内重新声明并重新分配了相同的JavaScript变量slider而导致的。您需要将slider的声明移到函数内部。

重新声明完全相同的功能并不会造成伤害,但效率很低而不是DRY。您应该将该函数移动到其自己的.js文件中,并使用<h:outputScript>将其包含在内。 JSF最终只会包含一次。然后,相应地更改函数以将变量作为参数。

像这样的东西

<h:outputScript library="composite" name="some.js" target="head" />
...
<h:panelGroup id="...">
    <p:selectOneMenu ... onchange="inOutChanged(this)">
        ...
    </p:selectOneMenu>
    ...
    <p:slider ... />
</h:panelGroup>

/resources/composite/some.js内(假设/resoruces/composite包含您的复合组件XHTML文件)

function inOutChanged(menuElement) {
    var $menu = $(menuElement);
    if ($menu.val() == "INC") {
        $menu.parent().find(".ui-slider").addClass("includedInRange");
    }
}

答案 1 :(得分:1)

您应该在更改事件侦听器中使用$(this)选择器:

$(".inOut").change(function(){
    var sel = $(this).find('option:selected').text();
    if(sel == 'INC') {
        //find slider and add class
    }
});

请注意,我绑定了组件范围之外的onchange事件侦听器,并找到了基于附加CSS类的组件。这可以在$(document).ready()内完成。

当然,您可以在JS函数中使用客户端ID,也可以将该函数绑定到组件的属性。