valueChangeListener 또는 f : ajax listener를 언제 사용합니까?


88

listener배치 와 관련하여 다음 두 코드의 차이점은 무엇입니까 ?

<h:selectOneMenu ...>
    <f:selectItems ... />
    <f:ajax listener="#{bean.listener}" />
</h:selectOneMenu>

<h:selectOneMenu ... valueChangeListener="#{bean.listener}">
    <f:selectItems ... />
</h:selectOneMenu>

답변:


184

valueChangeListener유일한 양식이 제출 될 때 호출됩니다 제출 값은 초기 값과 다릅니다. 따라서 HTML DOM 이벤트 실행될 때 호출되지 않습니다 change. HTML DOM change이벤트 중에 양식을 제출하려면 <f:ajax/>listener (!)없이 다른 양식 을 입력 구성 요소 에 추가해야합니다 . 현재 구성 요소 만 처리하는 양식 제출이 발생합니다 (에서와 같이 execute="@this").

<h:selectOneMenu value="#{bean.value}" valueChangeListener="#{bean.changeListener}">
    <f:selectItems ... />
    <f:ajax />
</h:selectOneMenu>

<f:ajax listener>대신을 사용하면 valueChangeListener기본적으로 HTML DOM change이벤트 중에 이미 실행됩니다 . UICommand확인란 또는 라디오 버튼을 나타내는 구성 요소 및 입력 구성 요소 내부 에서는 기본적으로 HTML DOM click이벤트 중에 만 실행 됩니다.

<h:selectOneMenu value="#{bean.value}">
    <f:selectItems ... />
    <f:ajax listener="#{bean.ajaxListener}" />
</h:selectOneMenu>

또 다른 주요 차이점은 단계 valueChangeListener가 끝날 때 메서드가 호출 된다는 것 PROCESS_VALIDATIONS입니다. 이때 제출 된 값은 아직 모델에서 업데이트되지 않았습니다. 따라서 입력 구성 요소에 바인딩 된 빈 속성에 액세스하는 것만으로는 얻을 수 없습니다 value. 으로 가져와야합니다 ValueChangeEvent#getNewValue(). 그런데 이전 값은에서도 사용할 수 있습니다 ValueChangeEvent#getOldValue().

public void changeListener(ValueChangeEvent event) {
    Object oldValue = event.getOldValue();
    Object newValue = event.getNewValue();
    // ...
}

<f:ajax listener>메서드는 INVOKE_APPLICATION단계 중에 호출됩니다 . 이때 제출 된 값은 이미 모델에서 업데이트되었습니다. 입력 구성 요소에 바인딩 된 빈 속성에 직접 액세스하여 가져올 수 있습니다 value.

private Object value; // +getter+setter.

public void ajaxListener(AjaxBehaviorEvent event) {
    System.out.println(value); // Look, (new) value is already set.
}

또한 제출 된 값을 기반으로 다른 속성 을 업데이트해야하는 경우 valueChangeListener업데이트 된 속성을 사용 하는 경우 이후 단계 에서 제출 된 값으로 재정의 될 있으므로 실패합니다 UPDATE_MODEL_VALUES. 당신은 오래된 JSF의 1.x 응용 / 자습서 / 자원에서 볼 이유는이 것을 정확히 valueChangeListener같은 구조가와 함께 사용되어에 immediate="true"FacesContext#renderResponse()일어나는 것을 방지 할 수 있습니다. 결국,를 사용하여 valueChangeListener비즈니스 작업을 실행하는 것은 실제로 항상 해킹 / 해결 방법이었습니다.

요약 : valueChangeListener실제 값 변경 자체를 가로 채야하는 경우에만 사용하십시오 . 즉, 실제로 이전 값과 새 값 모두에 관심이 있습니다 (예 : 기록).

public void changeListener(ValueChangeEvent event) {
    changeLogger.log(event.getOldValue(), event.getNewValue());
}

<f:ajax listener>새로 변경된 값에 대해 비즈니스 조치를 실행해야하는 경우에만 사용하십시오 . 즉, 실제로 는 새 값 에만 관심이 있습니다 (예 : 두 번째 드롭 다운 채우기).

public void ajaxListener(AjaxBehaviorEvent event) {
    selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown);
}

실제로 비즈니스 작업을 실행하는 동안 이전 값에 관심이있는 경우로 돌아가서 단계에 valueChangeListener대기열에 추가합니다 INVOKE_APPLICATION.

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

    Object oldValue = event.getOldValue();
    Object newValue = event.getNewValue();
    System.out.println(newValue.equals(value)); // true
    // ...
}

@BalusC, 전달되는 값으로 설정하기 전에 setter의 백업 개체에서 이전 값 을 가져 오지 않는 이유 가 있습니까? 다음과 같이 : . 그런 방식으로 얻은 이전 값과 새 값을 사용하여 간단한 로깅뿐만 아니라 setter에서 직접 비즈니스 논리 를 수행 할 수있는 것 같지만 이것이 부작용을 유발하는지 모르겠습니다.logger.trace( "setting changeTypes from {} to {}", this.changeTypes, changeTypes );
Lucas

완벽하고 완전한 답변! 지식을 공유해 주셔서 감사합니다!
hbobenicio

@BalusC는 AjaxBehaviorEvent를 통해 변경된 값을 얻을 수도 있습니까? 다른 구성 요소에 연결된 <h : selectManyListbox가 있고 변경된 (추가 / 제거됨)을 사용하여 작업을 수행하고 싶습니다
Paullo


감사합니다 @BalusC하지만 ValueChangeListener가 <f : ajax event = "valueChange"render = "tests"execute = "@ this"listener = "# {testController.txt"와 같이 실행 및 렌더링 값이 있으므로 내 경우에 적합 할 것이라고 생각하지 않습니다. processTimeTable} "/>
Paullo

9

첫 번째 조각의 경우 (ajax 리스너 속성) :

ajax 태그의 "listener"속성은 클라이언트 측에서 ajax 함수가 발생할 때마다 서버 측에서 호출되는 메소드입니다. 예를 들어이 속성을 사용하여 사용자가 키를 누를 때마다 호출 할 서버 측 함수를 지정할 수 있습니다.

그러나 두 번째 조각 (valueChangeListener) :

ValueChangeListener는 입력 값이 변경 될 때가 아니라 양식이 제출 될 때만 호출됩니다.

*이 편리한 답변 을보고 싶을 수도 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.