JSF 2.0: Übertragen Formularfelder mit Anfangsdaten unter Verwendung von scoped request-Bohnen (zum Update-Server-spezifischen Daten Stromkomponente)

StackOverflow https://stackoverflow.com/questions/3812685

Frage

Ein recht Normalfall:

Wir haben eine ‚Portlet‘ Verbundkomponente, die zwei Zustände hat: Auf- und Zuklappen. Portlets beginnen als erweiterte, aber Benutzer können sie auf ihnen, indem Sie kollabieren. Dieser Zustand soll die Sitzung gespeichert werden, so dass sobald den Benutzer der Seite aktualisiert oder navigiert zu einem neuen, die Portlets erinnern, wenn sie erweitert / geschlossen.

Dies ist der Kern des Problems : Wie würden Sie tatsächlich umsetzen solchen Zustand Spar in eine Komponente, die auf Seite mehrfach eingesetzt werden kann

Einige Hintergrundinformationen / Ideen:

Implementieren von state-Speichern für ein Portlet leicht unter Verwendung einer Session-scoped Bohne erreicht werden würde. Auch feste Anzahl von Portlets könnte durch die Schaffung eine feste Anzahl von Session-scoped Bohnen oder erklären unterschiedliche Eigenschaften in eine Bean unterstützt werden. Aber ich will nicht einmal erwähnen, warum diejenigen, nähert sich schlecht ist.

Meine erste Idee dafür war eine Karte (oder eine Objektstruktur) unter einzelnem Session-Bean zu erstellen, die die Zustände für alle Portlets zu halten. Ich kann aber nicht direkt auf diese Daten von JSF beziehen (so dass JSF würde auch sie aktualisieren). Ich hielt einen bestimmten Getter / Setter Schreiben den richtigen Wert in der Karte zu holen / aktualisieren, aber das ist nicht möglich, da es bei der Ausführung von Getter und Setter keine identifizierenden Daten ist.

Allerdings ist es wohl klar, dass ich die Zustände in einen Session-Bean zu speichern. Ich kann den Zustand Spar tut ziemlich leicht durch ein Formular mit f:ajax veröffentlichen und ein spezielles Verfahren listener und die übermittelten Daten ausgeführt wird. Um mehrere Instanzen der Komponente zu unterstützen, konnte ich (mehrere Instanzen) einer Anfrage-scoped Bean verwenden, um jede erweitern / Einsturz zu behandeln. Um jedoch tatsächlich die Daten zu veröffentlichen, die angibt, das Portlet und sein Zustand, ich zuerst müssen Sie es in den Formularfeldern in Render-Zeit.

So, wie man tatsächlich jedes Portlet mit richtigen Daten zur Verfügung stellen machen Zeit (eigentlich nur Zustandes boolean / ENUM in diesem Fall, aber einen Fall betrachtet, in dem mehr Daten gehandhabt werden sollen)?

Es scheint, dass:

  • h:inputHidden und h:inputText nicht unterstützen Anfangswert anders als als der Wert-Attribut (die #{portletBean.portletState} zeigen würde).
  • Ich kann nicht automatisch geladen Anfrage Bohnen mit richtigen Anfangswert auf ihrer Erstellungszeit, da es keine identifizierende Informationen zur Verfügung.

es Wieder einmal fühlt sich an wie ich etwas fehlt ... Zeiger?

Ich nehme an mindestens eine der Antworten auf der Verwendung UIComponent wäre eher als Verbundkomponenten, aber ich möchte dies als Verbundbauteil halten, da es viele rohen HTML-Elemente enthält.

Update:

  • Es ist ein ziemlich ähnlich Frage , mit Vorschlag zur Verwendung view-scoped Bohne. Ich glaube nicht, das lebensfähig ist hier aber nicht.
War es hilfreich?

Lösung 3

Ich habe eine vorher gelöst Hack eine Bean-Methode von JS aufzurufen:

Erstellt eine leere, unsichtbare Form, mit h:commandButton und f:ajax Inneren listener aufrufen.

eine separate Taste Erstellt für den Start des Aufklappen / Zuklappen Veranstaltung. Von dieser Taste initiieren JavaScript-Methode, die die Expansion / Zusammenbruch und zugleich beseelt klickt auf die versteckte Schaltfläche in dem Formular. Alle benötigten Daten werden mit dem listener Attribut gesendet. Listener zielt auf einen Session-Bean, die überprüft / aktualisiert eine Karte von Staaten, durch die Komponente der Client-IDs identifiziert.

Das ist ziemlich einfach, Wunder, warum habe ich nicht erkennen eariler ...

Es ist jedoch bei weitem noch nicht perfekt und es antwortet nicht, wie die Anfrage-scoped Bohnen mit Standardwerten ausgelöst werden könnten, sich als Lager- / Transportform zu verwenden.

Andere Tipps

habe ich ein paar möglichen Hacks dafür. Ich werde sie hier posten, aber ich glaube nicht, diese sind wirklich der Weg zu gehen:

Verwenden Sie Javascript Satz Formularfelder mit den richtigen Daten direkt nach dem Rendern:

window.addEvent('domready', function() {
    var portletState = '#{portletBean.getPortletState(cc.attrs.clientId)}';
    // find the field and set the data...
});

Man fühlt sich veery Hacky. Ich will nicht, diesen Weg nehmen.

Attribut-Karte Verwenden Komponente der Daten zu halten:

<cc:interface>
    <cc:attribute name="portletState" default="#{portletBean.getPortletState(cc.attrs.clientId)}" />
</cc:interface>

Der Zugang dass von Code:

public void stateChangedCallback(String clientId) {
    UIComponent component = FacesContext.getCurrentInstance().getViewRoot().findComponent(clientId);
    String state = (String) component.getAttributes().get("portletState");
}

fühlt sich auch nicht richtig. Ich bin auch nicht sicher, ob es funktioniert (Sie können EL tatsächlich nutzen in default-Attribute).

Verwenden Komponente Attribut Karte , um die Daten zu halten, indem sie bereitstellt, wenn die Komponente Aufruf:

<portlet:portlet id="specificPortlet">
    <f:attribute name="portletState" value="#{portletBean.getPortletState(component.clientId)}" />
</portlet:portlet>

Wieder sehr ungeschickt und dupliziert Code.

Sie können dies mit Taglibs tun, Sie Parameter in Tags passieren können:

Fügen Sie folgendes zu Ihrem taglib:

<tag>
    <tag-name>date</tag-name>
    <source>components/date.xhtml</source>
</tag>

Dann ist hier der Inhalt der Komponenten / date.xhtml

<ui:composition name="date_template">
    <h:panelGrid id="#{id}Panel" columns="1" border="0" cellpadding="0" cellspacing="0">
        <rich:calendar immediate="true" id="#{id}" popup="true" datePattern="dd.MM.yyyy"
                        enableManualInput="true" showApplyButton="true" cellWidth="12px" cellHeight="11px" style="width:100px"
                        value="#{dateForm.date}" required="#{required}" readonly="#{readonly}" validator="#{dateForm.validateDate}">
            <a4j:support event="onchanged" reRender="#{id}Panel,#{reRenderDate}"/>
            <ui:insert />
        </rich:calendar>

        <rich:message for="#{id}" errorClass="error" />
    </h:panelGrid>
</ui:composition>

Und dann verwenden Sie diese wie:

<adse:date id="dateTransfert" required="true"
           dateForm="#{dossierBean.dateTransfert}"
           readonly="false" reRenderDate="montantAncien,montantNouveau,montantEmolument">
     <a4j:support event="oninputblur" reRender="dateTransfertPanel,montantAncien,montantNouveau,montantEmolument"/>
</adse:date>

In diesem Fall wird Date in geben, dies ist ein Ziel, und in dem taglib wir verwenden, um Eigenschaften des Objekts (dateForm.date). Beachten Sie auch den. , die verwendet werden können, andere Elemente in der XHTML schließen

So können Sie in Kontext für jedes Portlet übergeben. Man könnte sogar diesen Standard machen, indem portletBean als übergeordnete Klasse, die den getPortletState () -Methode definiert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top