wake-up-neo.com

Wie kann ich eine ausgewählte Zeile in dataTable oder ui: repeat an commandLink übergeben?

Ich verwende Primefaces in einer JSF 2-Anwendung. Ich habe ein <p:dataTable> und anstatt Zeilen auszuwählen, möchte ich, dass der Benutzer verschiedene Aktionen direkt für einzelne Zeilen ausführen kann. Dafür habe ich mehrere <p:commandLink>s in der letzten Spalte.

Mein Problem: Wie kann ich der über den Befehlslink gestarteten Aktion eine Zeilen-ID übergeben, damit ich weiß, auf welche Zeile ich reagieren soll? Ich habe versucht, ein <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>

Aber es ergibt immer 0 - anscheinend ist die Zeilenvariable f nicht verfügbar, wenn das Attribut gerendert wird (es funktioniert, wenn ich einen festen Wert verwende).

Hat jemand eine alternative Lösung?

97

Was die Ursache betrifft, ist <f:attribute> Spezifisch für die Komponente selbst (während der Ansichtserstellungszeit ausgefüllt) und nicht für die iterierte Zeile (während der Ansichtsrenderzeit ausgefüllt).

Es gibt verschiedene Möglichkeiten, um die Anforderung zu erfüllen.

  1. Verwenden Sie stattdessen <f:param> . Es wird ein Anforderungsparameter hinzugefügt.

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

    Wenn Ihre Bean einen Anforderungsbereich hat, lassen Sie JSF sie auf @ManagedProperty setzen

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

    Oder wenn Ihre Bean einen breiteren Geltungsbereich hat oder Sie eine feinkörnigere Validierung/Konvertierung wünschen, verwenden Sie <f:viewParam> in der Zielansicht, siehe auch f: viewParam vs @ManagedProperty) :

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

    In beiden Fällen hat dies den Vorteil, dass das Datenmodell nicht unbedingt für die Formularübermittlung beibehalten werden muss (für den Fall, dass Ihre Bean einen Anforderungsbereich hat).


  2. Verwenden Sie stattdessen <f:setPropertyActionListener> . Der Vorteil besteht darin, dass der Zugriff auf die Anforderungsparameterzuordnung nicht mehr erforderlich ist, wenn die Bean einen breiteren Bereich als den Anforderungsbereich aufweist.

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

    In Kombination mit

    private Long id; // +setter
    

    Es ist nur über die Eigenschaft id in der Aktionsmethode verfügbar. Dies setzt lediglich voraus, dass das Datenmodell für die Formularübermittlungsanforderung beibehalten wird. Am besten setzen Sie die Bean mit @ViewScoped In den View-Scope.


  3. Wenn Ihr Servletcontainer Servlet 3.0/EL 2.2 unterstützt, übergeben Sie ihn einfach als Methodenargument. Dies erfordert auch, dass das Datenmodell für die Formularübermittlungsanforderung beibehalten wird. Am besten setzen Sie die Bean mit @ViewScoped In den View-Scope.

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

    In Kombination mit:

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

    Sie können sogar das gesamte Artikelobjekt übergeben:

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

    mit:

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

    Bei Servlet 2.5-Containern ist dies auch möglich, wenn Sie eine EL-Implementierung bereitstellen, die dies unterstützt, z. B. JBoss EL. Einzelheiten zur Konfiguration finden Sie unter diese Antwort .


  4. Binden Sie den datierbaren Wert an DataModel<E> , was wiederum die Elemente einschließt.

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

    mit

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

    (es transient zu machen und es träge im Getter zu instanziieren, ist obligatorisch, wenn Sie dies für eine Bean mit View- oder Session-Gültigkeitsbereich verwenden, da DataModel dies nicht tut implementiere Serializable)

    Dann können Sie mit DataModel#getRowData() auf die aktuelle Zeile zugreifen, ohne etwas herumzugeben (JSF bestimmt die Zeile basierend auf dem Anforderungsparameternamen des angeklickten Befehlslinks/der angeklickten Schaltfläche).

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

    Dies erfordert auch, dass das Datenmodell für die Formularübermittlungsanforderung beibehalten wird. Am besten setzen Sie die Bean mit @ViewScoped In den View-Scope.


  5. Sie können Application#evaluateExpressionGet() verwenden, um den aktuellen #{item} Programmgesteuert auszuwerten.

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

Welcher Weg gewählt wird, hängt von den funktionalen Anforderungen ab und davon, ob der eine oder andere weitere Vorteile für andere Zwecke bietet. Ich persönlich würde mit # 3 weitermachen oder, wenn Sie auch Servlet 2.5-Container unterstützen möchten, mit # 2.

213
BalusC

In JSF 1.2 wurde dies mit <f:setPropertyActionListener> (Innerhalb der Befehlskomponente) durchgeführt. In JSF 2.0 (EL 2.2, dank BalusC) ist es möglich, dies so zu tun: action="${filterList.insert(f.id)}

11
Bozho

In meiner Ansicht Seite:

<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>

stützbohne

 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;
        }
    }
}
11
Arfan J