Seçili satırı dataTable veya ui: tekrar içinde commandLink'e nasıl iletebilirim?


99

Bir JSF 2 uygulamasında Primefaces kullanıyorum. A sahibim <p:dataTable>ve satırları seçmek yerine, kullanıcının tek tek satırlarda çeşitli eylemleri doğrudan yürütebilmesini istiyorum. Bunun için <p:commandLink>son sütunda birkaç tane 'var .

Benim sorunum: hangi satırda işlem yapacağımı bilmek için komut bağlantısı tarafından başlatılan eyleme bir satır kimliğini nasıl iletebilirim? Bir kullanmayı denedim <f:attribute>:

<p:dataTable value="#{bean.items}" var="item">
    ...
    <p:column>
        <p:commandLink actionListener="#{bean.insert}" value="insert">
            <f:attribute name="id" value="#{item.id}" />
        </p:commandLink>
    </p:column>
</p:dataTable>

Ama her zaman 0 verir - görünüşe göre satır değişkeni föznitelik işlendiğinde kullanılamaz (sabit bir değer kullandığımda çalışır).

Herkesin alternatif bir çözümü var mı?

Yanıtlar:


215

Nedeni <f:attribute>ile ilgili olarak, yinelenen satıra (görünüm oluşturma süresi sırasında doldurulur) değil, bileşenin kendisine özgüdür (görünüm oluşturma süresi sırasında doldurulur).

Gereksinimi yerine getirmenin birkaç yolu vardır.

  1. Sunucu kapsayıcınız minimum Servlet 3.0 / EL 2.2 destekliyorsa, bunu UICommand bileşen veya AjaxBehavioretiketin eylem / dinleyici yöntemi argümanı olarak iletin . Örneğin

     <h:commandLink action="#{bean.insert(item.id)}" value="insert" />

    İle bütünlüğünde:

     public void insert(Long id) {
         // ...
     }

    Bu, yalnızca veri modelinin form gönderme isteği için korunmasını gerektirir. En iyisi, fasulyeyi görüş alanına koymaktır @ViewScoped.

    Hatta tüm öğe nesnesini bile iletebilirsiniz:

     <h:commandLink action="#{bean.insert(item)}" value="insert" />

    ile:

     public void insert(Item item) {
         // ...
     }

    Servlet 2.5 konteynerlerinde, JBoss EL gibi bunu destekleyen bir EL uygulaması sağlarsanız bu da mümkündür. Yapılandırma ayrıntısı için bu yanıta bakın .


  2. Kullanım <f:param>içinde UICommandbileşen. Bir istek parametresi ekler.

     <h:commandLink action="#{bean.insert}" value="insert">
         <f:param name="id" value="#{item.id}" />
     </h:commandLink>

    Fasulyeniz istek kapsamlıysa, JSF'nin bunu ayarlamasına izin verin @ManagedProperty

     @ManagedProperty(value="#{param.id}")
     private Long id; // +setter

    Veya fasulyenizin daha geniş bir kapsamı varsa veya daha ayrıntılı doğrulama / dönüştürme istiyorsanız <f:viewParam>, hedef görünümde kullanın , ayrıca bkz : f: viewParam vs @ManagedProperty :

     <f:viewParam name="id" value="#{bean.id}" required="true" />

    Her iki durumda da bu, veri modelinin form gönderimi için korunmasına gerek olmaması avantajına sahiptir (fasulyenizin istek kapsamlı olması durumunda).


  3. Kullanım <f:setPropertyActionListener>içinde UICommandbileşen. Bunun avantajı, çekirdeğin talep kapsamından daha geniş bir kapsama sahip olduğu zaman, istek parametresi eşlemesine erişim ihtiyacını ortadan kaldırmasıdır.

     <h:commandLink action="#{bean.insert}" value="insert">
         <f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" />
     </h:commandLink>

    İle bütünlüğünde

     private Long id; // +setter

    Yalnızca mülkiyet ideylem yöntemiyle kullanılabilir olacaktır. Bu, yalnızca veri modelinin form gönderme isteği için korunmasını gerektirir. En iyisi, fasulyeyi görüş alanına koymaktır @ViewScoped.


  4. DataModel<E>Bunun yerine, verileri sırayla sarmalayan tarihlenebilir değeri bağlayın .

     <h:dataTable value="#{bean.model}" var="item">

    ile

     private transient DataModel<Item> model;
    
     public DataModel<Item> getModel() {
         if (model == null) {
             model = new ListDataModel<Item>(items);
         }
         return model;
     }

    (bunu yapmak transientve alıcıda tembel bir şekilde örneklemek, bunu bir görünümde veya oturum kapsamlı fasulye üzerinde kullandığınızda zorunludur çünkü DataModeluygulanmaz Serializable)

    Ardından, geçerli satıra DataModel#getRowData()herhangi bir şey iletmeden erişebilirsiniz (JSF, satırı tıklanan komut bağlantısının / düğmesinin istek parametresi adına göre belirler).

     public void insert() {
         Item item = model.getRowData();
         Long id = item.getId();
         // ...
     }

    Bu aynı zamanda veri modelinin form gönderme isteği için korunmasını gerektirir. En iyisi, fasulyeyi görüş alanına koymaktır @ViewScoped.


  5. Application#evaluateExpressionGet()Akımı programlı olarak değerlendirmek için kullanın #{item}.

     public void insert() {
         FacesContext context = FacesContext.getCurrentInstance();
         Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class);
         Long id = item.getId();
         // ...
     }

Hangi yolu seçeceğiniz, işlevsel gereksinimlere ve birinin veya diğerinin başka amaçlar için daha fazla avantaj sunup sunmamasına bağlıdır. Ben şahsen # 1 ile devam ederdim veya servlet 2.5 konteynerleri de # 2 ile desteklemek istediğinizde.


1
+1, tercihim # 2'ye gitse de (2.5'in desteklenmesi gerekiyorsa).
Bozho

Kapsamlı cevap için teşekkürler. Ne yazık ki, # 1'in, filtrelenmiş veri tabanlarında çalışan tek şey olduğunu bildirmek zorundayım (tam da buna ihtiyacım olan senaryo bu). Diğerleri yalnızca filtrelenmemiş bir masa üzerinde çalıştı. Yine de bunu cevabınızdan çok ilkellerde bir hata olarak görüyorum.
Michael Borgwardt

Fasulye talebi veya görünümü kapsamlı mı?
BalusC

2
"Filtrelenmiş" ile bu vitrin örneğindeki gibi mi demek istiyorsunuz ? Belirtiler, filtre eyleminin yalnızca istemci tarafında gerçekleştiğini ve sunucu tarafındaki modelin korunmadığını gösterir. Bunun kasıtlı olup olmadığından emin değilim. Her zaman bir sorun raporu bırakabilirsiniz.
BalusC

Gönderiniz şimdiye kadar okuduğum en faydalı yazılar arasında. Yöntem 5'i kullandım çünkü sunucu uygulaması 2.5 kullanmaya zorlandım. Şimdi sorum şu: commandLink ile (örneğinizdeki gibi) ancak ajax kullanarak bir parametre göndermenin mümkün olup olmadığı?
Aditzu

11

JSF 1.2'de bu, <f:setPropertyActionListener>(komut bileşeni içinde) tarafından yapılmıştır. JSF 2.0'da (tam olarak EL 2.2, BalusC sayesinde) bunu şu şekilde yapmak mümkündür:action="${filterList.insert(f.id)}


6
Bu özellik JSF 2.0'a (kendi başına Servlet 2.5 kapsayıcılarında çalışabilir) değil, EL 2.2'ye (Servlet 3.0'ın bir parçası olan) özgüdür.
BalusC

11

Görünüm sayfamda:

<p:dataTable  ...>
<p:column>
<p:commandLink actionListener="#{inquirySOController.viewDetail}" 
               process="@this" update=":mainform:dialog_content"
           oncomplete="dlg2.show()">
    <h:graphicImage library="images" name="view.png"/>
    <f:param name="trxNo" value="#{item.map['trxNo']}"/>
</p:commandLink>
</p:column>
</p:dataTable>

destek fasulye

 public void viewDetail(ActionEvent e) {

    String trxNo = getFacesContext().getRequestParameterMap().get("trxNo");

    for (DTO item : list) {
        if (item.get("trxNo").toString().equals(trxNo)) {
            System.out.println(trxNo);
            setSelectedItem(item);
            break;
        }
    }
}

-1

Sayesinde Mkyong tarafından bu sitede , tek çözüm aslında bizim için çalışan bir parametre şuydu geçmek

<h:commandLink action="#{user.editAction}">
    <f:param name="myId" value="#{param.id}" />
</h:commandLink>

ile

public String editAction() {

  Map<String,String> params = 
            FacesContext.getExternalContext().getRequestParameterMap();
  String idString = params.get("myId");
  long id = Long.parseLong(idString);
  ...
}

Teknik olarak, yöntemin kendisine doğrudan geçemezsiniz, ancak JSF request parameter map.


1
Burada sorulandan farklı bir sorununuz var. #{param}İsteğe bağlı bir parametreyi iletmek için değil, sonraki istekler için haritadan istek parametrelerini saklamak istiyorsunuz . Soru-Cevap
bölümünüz
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.