2015-06-16 21 views
5

Ho una forma semplice che contiene una casella di modifica e un pulsante:validatori asincroni 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> 

Quando l'utente fa clic sul pulsante, un po 'la convalida di base è fatto e se tutto va bene, è aggiunta la voce ad una tabella di dati:

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

Ora, quello che voglio ottenere è quando l'utente inserisce un elemento, il primo, preliminare, la convalida è fatto e se la convalida è riuscita l'elemento viene aggiunto al tavolo dove la lista viene visualizzato insieme allo stato di convalida (ad es. convalida, non valido, valido). Quando l'elemento viene aggiunto alla tabella, viene avviata un'altra convalida, più dispendiosa in termini di tempo, e al termine della convalida viene aggiornato l'itemValidationStatus nella tabella. Non voglio bloccare l'utente durante la convalida che richiede tempo. Invece, voglio consentire all'utente di aggiungere più elementi mentre gli elementi già aggiunti vengono convalidati.

Vedo tre modi per risolvere questo:

  1. per registrare un qualche tipo di JS osservatore che reagire a un oggetto è in fase di aggiornamento nel bean gestito

  2. Per attivare il rendering da il bean gestito che renderebbe possibile genera un thread di convalida che, sulla rifinitura, innescare il rendering di

  3. C'è qualche modo per iniziare in modo asincrono la convalida tramite JS e registrare una funzione di callback che o attivare il rendering di o aggiornare il valore direttamente

Il problema è che non riesco a trovare nulla online che avrebbe indicami la giusta direzione Sto cercando di risolvere questo problema con un semplice JSF (senza Prime Faces o strumenti simili).

EDIT:

mi è stato suggerito un'altra domanda come un possibile duplicato (JSF, aggiornare periodicamente un componente con AJAX?). Non sto cercando una soluzione per sondare peridicamente, ma per aggiornare quando i dati sottostanti cambiano. E cambierà solo una volta, quindi la soluzione ovvia sarebbe un ascoltatore di eventi o simile. Certo, questo potrebbe anche essere risolto con sondaggi periodici, ma questo mi sembra un livello molto basso per quello che sto cercando.

+0

possibile duplicato (http://stackoverflow.com/questions/11228198/jsf-refresh-periodically-a-component-with-aax) – DavidS

+1

D'accordo quindi, non in realtà un duplicato. Mi chiedo se JSF sia adatto per questo. Correzione – DavidS

+2

: "plain JSF" (come OP intendeva solo il set di set di componenti JSF standard disponibile). OP è in questo modo davvero in grado di camminare sul proprio piede. Solo il futuro JSF 2.3 verrà fornito con il supporto push "nativo". – BalusC

risposta

1

Per ora ho risolto con le seguenti modifiche (ispirati a questa domanda relativa JQuery How to trigger JSF render from jQuery):

  1. ho aggiunto onevent="validateItemList" nel <f:ajax> tag della forma:

    <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 aggiunto un modulo nascosto con un pulsante nascosto che attiva la convalida in termini di tempo e ridisegna la tabella:

    <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. ho aggiunto una funzione di callback JS che il pulsante nascosto "spinge": [? JSF, aggiornare periodicamente un componente con ajax]

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

Grazie per la condivisione. Ecco la documentazione di [ajax onevent] (https://docs.oracle.com/javaee/6/tutorial/doc/gkddf.html): spiega da dove viene l'oggetto 'data'. Mi chiedo se ci sia qualche svantaggio nell'avere una richiesta "lunga" di ajax contro una spinta del server reale come volevi. – DavidS

+1

Sembra esserci un inconveniente: la connessione tra il client e il back-end sembra essere bloccata dal lungo sondaggio. Pertanto, durante la convalida che richiede molto tempo, il modulo non è in grado di inviare. Vedrò se sarà un problema o no. In tal caso dovrò utilizzare il polling a intervalli fino a quando il valore non sarà stato aggiornato. O forse dovrò introdurre un'altra biblioteca. – gabga

+0

Poiché non sono stati fatti altri suggerimenti, accetterò questa risposta. – gabga