Как получить обновленные значения модели в методе valueChangeListener?

Я застрял с проблемой в valueChangeListener. Я использую JSF 1.2 в Weblogic 6.0.

У меня есть страница, где в верхней части страницы есть 2 переключателя с именем Name1 и Name2. При нажатии Name1 под переключателями отображаются сведения Name1 (около 30 полей), а при нажатии Name2 отображаются сведения Name2. Теперь пользователь может обновить именованные детали, на которые нажали. например пользователь нажимает на Имя1 и изменяет поле адреса, а затем нажимает на Имя2 и изменяет возраст Имя2. Когда пользователь нажимает «Имя1», адрес должен отображаться обновленным с новым значением, и снова, когда пользователь нажимает «Имя2», возраст должен обновляться.

Я использовал valueChangeListener, чтобы справиться с этим, потому что мне нужно старое и новое значение измененного события. Проблема в том, что когда valueChangeListener вызывается в конце фазы VALIDATION, я не получаю обновленный адрес поля Name1 в методе valueChangeListener. Может ли кто-нибудь помочь мне найти обходной путь?


person Suman    schedule 05.01.2013    source источник


Ответы (2)


поскольку valueChangeListener вызывается в конце фазы ПРОВЕРКИ, я не получаю обновленный адрес поля Name1 в методе valueChangeListener

Поставьте событие в очередь на фазу INVOKE_ACTION, чтобы оно действовало как метод действия (слушателя).

public void valueChangeListenerMethod(ValueChangeEvent event) {
    if (event.getPhaseId() != PhaseId.INVOKE_APPLICATION) {
        event.setPhaseId(PhaseId.INVOKE_APPLICATION);
        event.queue();
        return;
    }

    // Do your original job here. 
    // It will only be entered when current phase ID is INVOKE_APPLICATION.
}

Поскольку фаза INVOKE_ACTION выполняется после фазы UPDATE_MODEL_VALUES, обновленные значения модели будут доступны "обычным способом".

person BalusC    schedule 05.01.2013
comment
Большое спасибо BalusC. Оно работает. Всякий раз, когда я застреваю в каких-то проблемах с JSF, я всегда ищу ваши предложения в stackoverflow и нахожу ваши ответы очень простыми и понятными. Еще раз спасибо. - person Suman; 07.01.2013
comment
Не связано напрямую с вопросом, но еще немного информации, если кто-то будет использовать это решение: имейте в виду, что если у вас есть какие-либо другие ValueChangeListeners, зарегистрированные для этого поля, они также будут запускаться дважды. Я предполагаю, что это тихий конкретный сценарий, но в любом случае полезно знать. - person whitesite; 26.07.2016
comment
ВАЖНОЕ примечание с моей стороны: событие помещается в конец очереди, поэтому, если у вас есть valueChangeEvent вместе с методом действия, событие будет выполнено ПОСЛЕ метода действия - обычно это не то, что вы хотите. Решение: переместите его в фазу Update-Model-Values, события будут выполняться после обновления модели (см. UIViewRoot.processUpdates()). Для этого я создал метод поддержки (см. мой ответ). - person Thies; 10.03.2021
comment
@Thies: это неправда. Скорее всего, вы неправильно использовали actionListener вместо action в качестве метода действия. Связано: stackoverflow.com/q/3909267 - person BalusC; 10.03.2021
comment
@BalusC: я тоже об этом думал, но получил исключение в моей программе из-за неправильного порядка выполнения (я проверил выполнение под контролем отладчика). По крайней мере, при использовании Trinidad ‹tr:commandButton› и jakarta.faces 2.3.14 метод действия ставится в очередь как событие для фазы IA до выполнения valueChangeListener. Таким образом, повторно поставленный в очередь VCE выполняется после метода действия. UIViewRoot.processApplication() просто выполняет трансляциюEvents(), после чего нет явного вызова метода действия (чего я изначально ожидал). - person Thies; 10.03.2021

(Расширение ответа BalusC)
Как отмечено в моем комментарии к ответу BalusC, здесь метод поддержки с примером использования:

public static boolean moveToEndOfUpdateModel(FacesEvent event) {
    if (event.getPhaseId() == null  ||  event.getPhaseId().getOrdinal() < PhaseId.UPDATE_MODEL_VALUES.getOrdinal()) {
        // see UIViewRoot.processUpdates():  first components.processUpdates(), then broadcastEvents()
        event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
        event.queue();
        return true;
    }
    return false;
}

(И еще раз повторю причину моего соответствующего изменения:
Событие помещается в конец очереди, поэтому, если у вас есть valueChangeEvent вместе с метод действия, событие будет выполнено после метода действия - обычно это не то, что вы хотите.)

В методе слушателя я использую его так:

public void myValueChangeMethod(ValueChangeEvent vce) {
    if (JSFUtils.moveToEndOfUpdateModel(vce))  return;
    // ... perform my actions here, with access to already updated bean values ...
}

А для JSF 2+ вам лучше использовать <f:ajax listener="..."> - если вы не вынуждены использовать библиотеку компонентов, не поддерживающую это (как старый Тринидад).

person Thies    schedule 10.03.2021