ValueChangeListener veya f: ajax dinleyicisi ne zaman kullanılır?


88

listenerYerleştirme açısından aşağıdaki iki kod parçası arasındaki fark nedir ?

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

ve

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

Yanıtlar:


184

valueChangeListenerSadece form gönderildiğinde çağrılır ve gönderilen değer başlangıç değerinden farklıdır. Bu nedenle, yalnızca HTML DOM changeolayı tetiklendiğinde çağrılmaz . HTML DOM changeetkinliği sırasında formu göndermek isterseniz <f:ajax/>, giriş bileşenine dinleyici (!) Olmadan başka bir form eklemeniz gerekir . Yalnızca mevcut bileşeni (olduğu gibi execute="@this") işleyen bir form gönderilmesine neden olur .

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

<f:ajax listener>Bunun yerine kullanıldığında valueChangeListener, varsayılan olarak changezaten HTML DOM etkinliği sırasında yürütülür . İçinde UICommandbileşenleri ve bir onay kutusu veya RadioButton temsil girdi bileşenleri, HTML DOM sırasında çalıştırılan varsayılan olarak olurdu clicksadece olayın.

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

Diğer bir önemli fark, valueChangeListeneryöntemin PROCESS_VALIDATIONSaşamanın sonunda devreye girmesidir . O anda, gönderilen değer modelde henüz güncellenmemiştir. Dolayısıyla, giriş bileşenine bağlı olan bean özelliğine erişerek bunu elde edemezsiniz value. Bunu almalısın ValueChangeEvent#getNewValue(). Bu arada eski değer de mevcuttur ValueChangeEvent#getOldValue().

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

<f:ajax listener>Yöntem sırasında çağrılan INVOKE_APPLICATIONfaz. O anda, sunulan değer modelde zaten güncellenmiştir. Girdi bileşenine bağlı olan bean özelliğine doğrudan erişerek bunu elde edebilirsiniz value.

private Object value; // +getter+setter.

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

Güncelleştirmek gerekir Ayrıca, başka gönderilen değerine dayalı mülkiyet, o zaman kullandığınız zaman başarısız olur valueChangeListenergüncellenmiş özellik olarak yapabilirsiniz müteakip sırasında gönderilen değerin geçersiz kılınabilir UPDATE_MODEL_VALUESfazı. İşte tam da bu yüzden eski JSF 1.x uygulamalarında / öğreticilerinde / kaynaklarında a'nın valueChangeListenerböyle bir yapıda olduğunu immediate="true"ve bunun FacesContext#renderResponse()olmasını önlemek için birlikte kullanıldığını görüyorsunuz . Sonuçta, valueChangeListeneriş eylemlerini yürütmek için kullanmak aslında her zaman bir hack / geçici çözüm olmuştur.

Özetle: valueChangeListenerGerçek değer değişikliğinin kendisine müdahale etmeniz gerekiyorsa yalnızca kullanın . Yani aslında hem eski hem de yeni değerle ilgileniyorsunuz (örneğin bunları kaydetmek için).

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

Kullanın <f:ajax listener>Eğer yeni değiştirdiğiniz değeri üzerinde bir iş işlemi çalıştırmak için gereken yalnızca. Yani aslında yalnızca yeni değerle ilgileniyorsunuz (örneğin, ikinci bir açılır menüyü doldurmak için).

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

Bir ticari eylemi gerçekleştirirken aslında eski değerle de ilgileniyorsanız, o zaman geri dönün valueChangeListener, ancak INVOKE_APPLICATIONaşamada sıraya koyun .

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, ayarlayıcıdaki arkalık nesnesinden eski değeri , aktarılan yeni değere ayarlamadan önce almamanın bir nedeni var mı? Böyle bir şey: logger.trace( "setting changeTypes from {} to {}", this.changeTypes, changeTypes );. Bu şekilde elde edilen eski ve yeni değerleri doğrudan ayarlayıcıda iş mantığı ve basit günlük kaydı yapmak için kullanabilirsiniz gibi görünüyor , ancak bunun yan etkilere neden olup olmayacağını bilmiyorum ...
Lucas

Mükemmel ve eksiksiz cevap! Bilgilerinizi paylaştığınız için teşekkür ederiz!
hbobenicio

@BalusC, AjaxBehaviorEvent aracılığıyla değiştirilen değeri de almak mümkün mü? Diğer bileşenlere zincirlenmiş <h: selectManyListbox'ım var ve bazı eylemleri gerçekleştirmek için değiştirileni (Eklendi / Kaldırıldı) kullanmak istiyorum
Paullo


Teşekkürler @BalusC Ancak, <f: ajax event = "valueChange" render = "testler" execute = "@ this" listener = "# {testController gibi bazı çalıştırma ve işleme değerlerine sahip olduğum için ValueChangeListener'ın durumuma uyacağını sanmıyorum. processTimeTable} "/>
Paullo

9

ilk parça için (ajax dinleyici niteliği):

Bir ajax etiketinin "dinleyici" niteliği, ajax işlevi istemci tarafında her gerçekleştiğinde sunucu tarafında çağrılan bir yöntemdir. Örneğin, bu özniteliği, kullanıcı bir tuşa her bastığında çağırmak üzere bir sunucu tarafı işlevi belirtmek için kullanabilirsiniz.

ancak ikinci parça (valueChangeListener):

ValueChangeListener, girdinin değeri değiştirildiğinde değil, yalnızca form gönderildiğinde çağrılacaktır.

* bu kullanışlı cevabı görmek isteyebilirsiniz

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.