2016-04-10 5 views
1

Ich habe die folgende Befehlsschaltfläche in der Ansicht hinzufügen „Speicher“:Zugriff PrimeFaces Befehlsschaltfläche aus Bohnen Aktion Hörer mit ID

 <p:panel style="border:none;text-align:left;margin:0;"> 

      <p:commandButton value="Save Document" id="save" icon="fa fa-save" 
       disabled="#{dIGRCController.digrc.qconce == '020'}"> 

       <f:param name="validate" value="true" /> 

      </p:commandButton> 

      <p:commandButton value="Clear" icon="fa fa-undo"></p:commandButton> 

     </p:panel> 

ich dynamisch bin versucht, um eine andere Action zuweisen. Wenn der Benutzer einen neuen Datensatz einfügen möchte, möchte ich, dass er die Einfügemethode aufruft. Wenn der Benutzer einen vorhandenen Datensatz aktualisieren möchte, sollte er die Aktualisierungsmethode aufrufen.

Im Moment bin ich versucht, dies zu tun:

@PostConstruct 
public void init() { 

    // setting the action listener of the Save Document button 
    UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot(); 

    // UIComponent button = viewRoot.findComponent("save"); 

    CommandButton button = (CommandButton) viewRoot.findComponent("save"); 

    FacesContext context = FacesContext.getCurrentInstance(); 

    MethodExpression methodExpression = context 
      .getApplication() 
      .getExpressionFactory() 
      .createMethodExpression(context.getELContext(), 
        "#{dIGRCController.updateDocument}", null, 
        new Class[] { DIGRCController.class }); 

    button.addActionListener(new MethodExpressionActionListener(
      methodExpression)); 

} 

Ich bin eine Null-Zeiger-Ausnahme auf der Linie erhalten:

button.addActionListener(new MethodExpressionActionListener(
     methodExpression)); 

Was mache ich falsch? Gibt es einen anderen Weg, um das zu erreichen, was ich versuche? Ich benutze JSF 2.2, PrimeFaces 5.3 und OmniFaces 1.11.

+1

'findComponent()' übernimmt die Client-ID als Argument, nicht die Komponenten-ID. Aber das sieht alles zu kompliziert aus. Das Definieren der Ansicht geschieht normalerweise in der XHTML-Datei, nicht in der Java-Klasse. Das Manipulieren des Komponentenbaums auf Java-Seite ist eine schlechte Übung. Sie können JSTL besser dafür verwenden, so dass Sie einfach XHTML verwenden können, das so viel selbst-dokumentierender ist als das Definieren von Komponenten/Attributen als Java-Code. – BalusC

+0

Verstanden. Ich habe auch über zwei Befehlsschaltflächen nachgedacht: Update und ein weiteres Insert. Und Rendering eine gegeben Bedingung für die Aktualisierung und die andere mit einigen einfügen Bedingung. Was denkst du über dieses Design @BalusC? – Erick

+0

Hängt davon ab, woher der Zustand kommt, aber das ist in der Tat ein Weg. Wenn die Bedingung auf der Zeit für die Erstellung von Views basiert, könnten Sie eine einzelne Befehlsschaltfläche mit einem '' verwenden, was im Grunde dasselbe ist wie Ihr Java-Code-Versuch. – BalusC

Antwort

1

Die findComponent() nimmt eine Client-ID als Argument und keine Komponenten-ID. Die Client-ID entspricht genau dem Wert des generierten HTML-Attributs id, das der betreffenden Komponente zugeordnet ist. Im Fall einer Befehlsschaltfläche wird normalerweise die Komponenten-ID des übergeordneten Elements <h:form> vorangestellt, getrennt durch das Namenscontainer-Trennzeichen, das standardmäßig : lautet.

dies angesichts

<h:form id="form"> 
    <p:commandButton id="save" ... /> 
</h:form> 

die Client-ID wäre form:save.

CommandButton button = (CommandButton) viewRoot.findComponent("form:save"); 

Siehe auch diese Frage im Zusammenhang zu identifizieren und mit Client-ID: How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"


Unrelated auf das konkrete Problem, das Komponentenbaum in Java Seite zu manipulieren eine schlechte Praxis ist. Sie sollten besser XHTML + XML verwenden, da dies sehr viel selbstdokumentierender ist als das Deklarieren/Definieren von Baumstrukturen. Sie können JSTL-Tags verwenden, um die Ansicht dynamisch zu erstellen (Hinweis: Dies unterscheidet sich von der dynamischen Darstellung der Ansicht unter Verwendung des Attributs rendered!).

z.

<p:commandButton ... action="#{bean.save}"> 
    <c:if test="#{bean.existing}"> 
     <f:actionListener binding="#{bean.needsUpdate()}" /> 
    </c:if> 
</p:commandButton> 

Siehe auch JSTL in JSF2 Facelets... makes sense?

Noch mehr, man muss nur #{bean.existing} als Methode Argument übergeben konnte.

<p:commandButton ... action="#{bean.save(bean.existing)}" /> 

Beide Ansätze sind wiederum zwar irgendwie komisch, wenn #{bean.existing} die gleiche Bohne wie #{bean.save} bezieht. Sie können dafür innerhalb #{bean.save} selbst nachsehen.

public void save() { 
    if (existing) { 
     // UPDATE 
    } else { 
     // INSERT 
    } 
} 

Weiter geht es, das ist IMO nicht die Verantwortung der Frontend-Ebene, sondern der Service-Schicht. Sie übergeben die gesamte Entität an die Serviceschicht, die wiederum basierend auf PK prüft, ob sie vorhanden ist oder nicht.

if (entity.getId() == null) { 
    // INSERT 
} else { 
    // UPDATE 
} 
+0

Super! Ich liebe diese Lösung. Ist viel besser als das, was ich über das Erstellen von zwei Schaltflächen und das Rendern gesagt habe! Danke @BalusC! – Erick

+0

Gern geschehen. – BalusC

Verwandte Themen