Когда составной компонент, содержащий код JS, отображается несколько раз, JS работает только с последним компонентом

У меня есть составной компонент, который использует 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 ответа

Решение

Ваша конкретная проблема вызвана тем, что вы повторно объявили и переназначили одну и ту же переменную JavaScript slider в глобальном масштабе. Вам необходимо переместить декларацию slider внутрь функции.

Переопределение точно такой же функции не вредит, но неэффективно и не СУХО. Вы должны переместить функцию в свою .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");
    }
}

Вы должны использовать $(this) селектор в вашем слушателе событий изменения:

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

Обратите внимание, что я ограничил прослушиватели событий onchange за пределами области действия компонента и нашел компоненты на основе присоединенного класса CSS. Это может быть сделано в течение $(document).ready(),

Конечно, вы можете использовать идентификаторы клиента в функции JS или связать эту функцию с атрибутом компонента.

Другие вопросы по тегам