2015-06-16 5 views
5

Ich habe ein einfaches Formular ein Bearbeitungsfeld und eine Schaltfläche enthält:Asynchronous Validatoren in JSF

<h:form id="addForm"> 
    <h:outputLabel value="Add item here" /><br /> 
    <p><h:inputText id="itemInput" value="#{myController.itemToAdd}" validator="myValidator" /> 
    <h:message for="itemInput" /></p> 
    <h:commandButton value="Add" action="#{myController.addItemToList}"> 
     <f:ajax execute="@form" render="@form :addedItems" /> 
    </h:commandButton> 
</h:form> 

Wenn der Benutzer klickt auf die Schaltfläche, einige grundlegende Validierung erfolgt und wenn alles in Ordnung ist, wird das Element hinzugefügt zu einer Datentabelle:

<h:panelGrid id="addedItems"> 
    <h:dataTable value="#{myController.itemMap.entrySet()}" var="itemMapEntry" > 
     <h:column> 
      <f:facet name="header"> 
       <h:outputText value="Items" /> 
      </f:facet> 
      <h:commandButton value="Remove/Modify" action="#{myController.removeItemFromList(itemMapEntry.getKey())}"> 
       <f:ajax render=":addedItems :addForm" /> 
      </h:commandButton> 
      <h:outputText value="#{itemMapEntry.getKey()}" /> 
     </h:column> 
     <h:column> 
      <f:facet name="action"> 
       <h:outputText value="" /> 
      </f:facet> 
      <h:outputText value="#{itemMapEntry.getValue().toString()}" id="itemValidationStatus" /> 
     </h:column> 
    </h:dataTable> 
</h:panelGrid> 

Nun, was ich will ist erreichen, wenn der Benutzer ein Element eintritt, wird die erste, vorläufige, Validierung durchgeführt und wenn die Validierung der Punkt gelungen ist, an den Tisch, wo die Liste hinzugefügt wird zusammen mit dem Validierungsstatus angezeigt (z. B. Validieren, Ungültig, Gültig). Wenn das Element zur Tabelle hinzugefügt wird, startet eine andere, zeitraubendere Validierung, und wenn die Überprüfung abgeschlossen ist, wird der itemValidationStatus in der Tabelle aktualisiert. Ich möchte den Benutzer während der zeitaufwendigen Validierung nicht blockieren. Stattdessen möchte ich dem Benutzer erlauben, weitere Elemente hinzuzufügen, während die bereits hinzugefügten Elemente überprüft werden.

Ich sehe drei Möglichkeiten, dies zu lösen:

  1. Um eine Art von JS Beobachter zu registrieren, die auf ein Objekt reagiert wird

    in der Managed Bean aktualisiert
  2. die Wiedergabe auszulösen aus die Managed Bean, die es möglich, um laichen eine Validierung Thread machen würde, das würde bei Beendigung auslösen die Rendering

  3. Es gibt eine Möglichkeit, asynchron die Validierung über JS zu starten und eine Rückruffunktion registrieren, die entweder die Rendering oder aktualisieren Sie den Wert löst direkt

Das Problem ist, dass ich nicht alles online finden können, würde Zeige mir in die richtige Richtung. Ich versuche das mit einfachem JSF zu lösen (ohne Prime Faces oder ähnliche Tools).

EDIT:

Ich war eine andere Frage als mögliches Duplikat vorgeschlagen (JSF, aktualisieren Sie regelmäßig eine Komponente mit Ajax?). Ich suche nicht nach einer peridischen Abfrage, sondern nach einer Aktualisierung der zugrunde liegenden Daten. Und es wird sich nur einmal ändern, also wäre die offensichtliche Lösung ein Event Listener oder ähnliches. Natürlich könnte dies auch durch periodische Umfragen gelöst werden, aber das scheint für das, wonach ich bin, sehr niedrig zu sein.

+0

möglich Duplikat (http://stackoverflow.com/questions/11228198/jsf-refresh-periodisch-a-komponente-mit-ajax) – DavidS

+1

Einverstanden, nicht wirklich ein Duplikat. Ich frage mich, ob JSF dafür gut geeignet ist. – DavidS

+2

Korrektur: "plain JSF" (wie OP gemeint mit nur dem verfügbaren Satz von Standard-JSF-Komponentensatz). OP ist in der Tat wirklich auf eigenen Füßen getreten. Nur zukünftige JSF 2.3 wird vielleicht mit "nativer" Push-Unterstützung kommen. – BalusC

Antwort

1

Vorerst gelöst ich es mit den folgenden Änderungen (inspiriert von dieser JQuery Zusammenhang Frage How to trigger JSF render from jQuery):

  1. I onevent="validateItemList" im <f:ajax> Tag der Form hinzugefügt:

    <h:form id="addForm"> 
        <h:outputLabel value="Add item here" /><br /> 
        <p><h:inputText id="itemInput" value="#{myController.itemToAdd}" validator="myValidator" /> 
        <h:message for="itemInput" /></p> 
        <h:commandButton value="Add" action="#{myController.addItemToList}"> 
         <f:ajax execute="@form" onevent="validateItemList" render="@form :addedItems" /> 
        </h:commandButton> 
    </h:form> 
    
  2. I ein verstecktes Formular mit einer versteckten Schaltfläche hinzugefügt, die die zeitaufwendige Überprüfung auslöst und die Tabelle neu rendert:

    <h:form id="hiddenForm"> 
        <h:commandButton value="" action="#{myController.validateItemMap}" id="validatorButton" style="display:none"> 
         <f:ajax execute="@form" render=":addedItems" /> 
        </h:commandButton> 
    </h:form> 
    
  3. ich einen Rückruf JS-Funktion hinzugefügt, dass "schiebt" die versteckte Taste: [? JSF, aktualisieren Sie regelmäßig eine Komponente mit Ajax]

    <script type="text/javascript"> 
        function validateItemList(data){ 
         if(data.status == "success"){ 
          document.getElementById("hiddenForm:validatorButton").click(); 
         } 
        } 
    </script> 
    
+1

Danke für die Freigabe. Hier ist die Dokumentation für [ajax onevent] (https://docs.oracle.com/javaee/6/tutorial/doc/gkddf.html): Hier wird erklärt, woher dieses 'data'-Objekt stammt. Ich frage mich, ob es einen Nachteil gibt, eine "lange" Ajax-Anfrage gegenüber einem tatsächlichen Server-Push zu haben, wie Sie es wollten. – DavidS

+1

Es scheint einen Nachteil zu geben - die Verbindung zwischen dem Client und dem Backend scheint durch die lange Umfrage blockiert zu sein. Während der zeitaufwendigen Validierung kann das Formular daher nicht übermittelt werden. Ich werde sehen, ob es ein Problem sein wird oder nicht. In diesem Fall muss ich die Intervallabfrage verwenden, bis der Wert aktualisiert wurde. Oder vielleicht muss ich eine andere Bibliothek einführen. – gabga

+0

Da keine weiteren Vorschläge gemacht wurden, werde ich diese Antwort akzeptieren. – gabga