2009-12-21 6 views
8

Bevor ich auf, sehen diese questionWie kann ich einen JSF-Komponentenwert mithilfe von EL abrufen?

Es ist JSF Form wieder wie folgt dargestellt:

Hinweis

<f:view> 
    <h:form> 
     <div> 
      <label>Id</label> 
      <input type="text" name="accountId"/> 
     </div> 
     <div> 
      <label>Amount</label> 
      <input type="text" name="amount"/> 
     </div> 
     <h:commandButton value="Withdraw" action="#{accountService.withdraw(param.accountId, param.amount)}"/> 
    </h:form> 
</f:view> 
, die ich <input type="text" name="amount"> statt <h:inputText id="amount"> verwendet haben. Um den Wert mithilfe von Seam EL Resolver abzurufen, verwende ich param.amount.

Es passiert, dass, wenn ich <input type="text" benutze und etwas auf der Serverseite schief geht, muss ich die Seite erneut anzeigen. Daher wird der übermittelte Wert nicht abgerufen, da es sich um einen einfachen HTML-Code handelt. Aus diesem Grund muss ich stattdessen eine JSF-Komponente <h:inputText verwenden.

Die Frage ist also: Wie kann ich einen <h:inputText JSF-Komponente Wert mit Expression Language abrufen?

+0

zu starten, war Ihre Frage ziemlich verwirrend. Es sieht so aus, als wäre die Seam-Geschichte hier völlig irrelevant. Bitte posten Sie in der Zukunft den JSF-Code, den Sie ** tatsächlich ** haben und sagen Sie, was genau Sie mit ** Ihrem ** Code machen wollen. – BalusC

+0

Das macht auch keinen Sinn. Im einfachen JSP/Servlet hätten Sie '' dafür verwenden können. – BalusC

+0

Ich empfehle dringend, sich durch ein anständiges JSF-Buch/Tutorial zu begeben, um zu verstehen, wie JSF "unter der Haube" funktioniert. Auch das Lernen von "Plain Vanilla" JSP/Servlet würde viel dazu beitragen, es zu verstehen. Sie machen Vermutungen und versuchen, JSFs Ideologie zu brechen, indem Sie all ihre Arbeit in Ihren eigenen Händen übernehmen. Tut mir leid, wenn ich hart klingen sollte, aber das ist die Wahrheit. – BalusC

Antwort

18

JSF-Client-IDs werden von der cliend ID der Eltern UINamingContainer Komponenten vorangestellt (z.B. h:form, h:dataTable, f:subview). Wenn Sie die generierte HTML-Quelle in Ihrem Webbrowser überprüfen (Rechtsklick, Quelltext anzeigen), sollten Sie sie sehen. Die id und name der generierten Eingabeelemente werden mit der id der übergeordneten Form vorangestellt. Sie müssen denselben Namen als Schlüssel in der Parameterzuordnung verwenden. Da das Trennzeichen, der Doppelpunkt :, ein "illegales" Zeichen in EL ist, müssen Sie die Klammernotation param['foo:bar'] verwenden, um sie abzurufen.

<f:view> 
    <h:form id="account"> 
     <div> 
      <label>Id</label> 
      <h:inputText id="id" /> 
     </div> 
     <div> 
      <label>Amount</label> 
      <h:inputText id="amount" /> 
     </div> 
     <h:commandButton value="Withdraw" 
      action="#{accountService.withdraw(param['account:id'], param['account:amount'])}"/> 
    </h:form> 
</f:view> 

ohne Naht-EL-ähnliche Verfahrensparameter (Sie wollen offenbar nicht/es haben), können Sie diese auch im Anforderungsparameterkarte mit dem Client-IDs als Schlüssel zugreifen können:

public void withDraw() { 
    Map<String, String> map = FacesContext.getCurrentInstance().getRequestParameterMap(); 
    String id = map.get("account:id"); 
    String amount = map.get("account:amount"); 
    // ... 
} 

Unnötig zu sagen, dass das böse ist. Machen Sie einfach die normale JSF-Methode, binden Sie die Werte mit den Bean-Eigenschaften.

Edit: nach der letzten Frage, die Sie bearbeitet haben:

Die Frage ist also: Wie rufe ich einen <h:inputText JSF-Komponentenwert durch Expression Language verwenden?

Dies ist bereits zuvor beantwortet. Verwenden Sie den JSF-generierten Namen als Parametername. Dies ist normalerweise in dem Muster von formId:inputId, wobei formId der id der Mutterkomponente UIForm Komponente ist und die inputId die id der UIInput Komponente ist. Überprüfen Sie die generierte HTML-Ausgabe auf den genauen Namen des generierten Feldes <input type="text">. Um den Parameterwert zu erhalten, verwenden Sie die Klammernotation ['name'], da Sie den Doppelpunkt : in EL nicht wie in ${param.formId:inputId} verwenden können.

So:

#{param['formId:inputId']} 
+0

Hm, das war deine eigene Antwort und das sollte funktionieren? Nun, ich kann nur andeuten, die generierte HTML-Ausgabe zu überprüfen, um zu sehen, ob die Namen stimmen und/oder ob sie in der Request-Parameter-Map verfügbar sind. – BalusC

+0

Sie sagen also, dass Sie * tatsächlich * einen 'h: inputText' in Ihrer JSF-Seite haben und nicht' '? Auf diese Weise müssen Sie ihm (und dem Elternformular) eine "ID" geben und den Parameter mit der generierten Client-ID als Schlüssel erhalten. Ich werde meine Antwort bald bearbeiten. – BalusC

+0

Sie befinden sich in der Anforderungs-Parameterzuordnung. Haben Sie zum Beispiel den Inhalt debuggt? 'System.out.println (requestParameterMap);' damit Sie sie und die Muster sehen können? – BalusC

1

Die Parameternamen/IDs für inputText werden durch die Steuer-Renderer eingekapselt sind und letztlich ein Implementierungsdetail. In der Praxis verwenden sie die clientId. Es sollte nicht notwendig sein, diese direkt von der Parameterkarte zu lesen; Verwenden Sie Wertbindung, um sie in das Modell zu schieben und von dort zu lesen.

Sie können Werte direkt von der Komponente mithilfe von EL lesen, indem Sie die Komponente an eine verwaltete Bean binden. Der Einfachheit halber ist hier eine Schranke auf die Anfrage Anwendungsbereich:

<!-- bind a UIComponent to the request map as "foo" --> 
<h:inputText binding="#{requestScope.foo}" /> 
<!-- read value from a UIComponent that implements ValueHolder --> 
#{requestScope.foo.value} 

Aber im Allgemeinen, gibt es keinen Vorteil dabei über:

<!-- bind a value to the request map as "foo" --> 
<h:inputText value="#{requestScope.foo}" /> 
<!-- read value from the request scope --> 
#{requestScope.foo} 

Um zu vermeiden, die Anfrage Karte verschmutzen (die über in Kollisionen führen kann Views), verwenden Sie eine verwaltete Bean, um den Namespace/kapseln Sie Ihre Werte, anstatt den Anforderungsbereich direkt zu verwenden.

+0

Gut insig, MCDowell. (+1) –

0

Obwohl i JSF-Komponentenwert durch die Client-ID abrufen kann, gibt es einige Nachteile sind wie folgt:

  1. Nach McDowell Antwort, die Client-ID ist eine Implementierung Detail
  2. Die Client-ID von dem abweichen kann die Komponenten-ID, wenn in der Steuerhierarchie mehr als ein Benennungscontainer vorhanden ist. (JSF in Buch Aktion)

Also, wenn Sie nicht möchten, dass auf Client-ID verlassen, können Sie Ihre eigene ElResolver wie folgt implementieren:

public class ComponentIdResolver extends ELResolver { 

    public Object getValue(ELContext context, Object base, Object property) { 
     if (base instanceof UIComponent && property instanceof String) { 
      UIComponent r = ((UIComponent) base).findComponent((String) property); 

      if (r != null) { 
       context.setPropertyResolved(true); 

       return r; 
      } 
     } 

     return null; 
    } 

} 

Jetzt kann ich so etwas wie verwenden (Beachten Sie zurückziehen Methode)

<h:inputText id="accountId" /> 
<h:inputText id="amount" /> 
<h:commandButton value="Withdraw" action="#{accountService.withdraw(view.accountId.value, view.amount.value)}"/> 

Ansicht ist ein implizites JSF-Objekt (ähnlich FacesContext.getCurrentInstance(). getViewRoot())

Dann reg ISTER Ihre ELResolver wie unten dargestellt (faces-config.xml)

<application> 
    <el-resolver>br.com.view.resolver.ComponentIdResolver</el-resolver> 
</application> 

Wenn Sie einen guten Einblick über ElResolver Extending the Java EE Unified Expression Language with a Custom ELResolver

Grüße sehen wissen wollen,