2013-01-14 3 views
8

Ho una pagina CRUD che mostra i dati da una query (un elenco di oggetti di dominio) in un datatable Primefaces.Keep <p:dialog> aperto quando la convalida non è riuscita

<p:dataTable 
       id="negozi" 
       var="n" 
       value="#{nController.theListFromQuery}" 
       rowKey="#{n.id}" 
       selection="#{nController.selected}" 
       selectionMode="single"> 

       <p:column headerText="Field1"> 
        <h:outputText value="#{n.f1}" /> 
       </p:column> 
       <p:column headerText="Field2"> 
        <h:outputText value="#{n.f2}" /> 
       </p:column> 
<p:column style="width:4%"> 
        <p:commandButton 
         actionListener="#{nController.prepareEdit(n)}" 
         update=":editDialogId" 
         oncomplete="editDialog.show()" 
         value="Edit" /> 
       </p:column> 
... 

Cliccando sul pulsante Modifica una finestra verrà mostrata:

<p:dialog 
       header="Edit N" 
       widgetVar="editDialog" 
       id="editDialogId"> 

        <h:form id="formDialog"> 

         <h:panelGrid id="editDialogTable" columns="2" cellpadding="10" style="margin:0 auto;"> 

          <p:outputLabel for="field1" value="F1:" /> 
          <p:inputText id="field1" value="#{nController.selected.f1}" /> 
          <p:outputLabel for="field2" value="F2:" /> 
          <p:inputText id="field2" value="#{nController.selected.f2}" /> 
<p:commandButton 
         value="Confirm" 
         actionListener="#{nController.doEdit}" 
         update=":form" 
         oncomplete="editDialog.hide()" 
         rendered="#{nController.selected.id!=null}" />     
... 

Funziona. Ora voglio fare di F1 un campo obbligatorio.

Aggiungo l'attributo "richiesto" al campo di testo di input e cosa succede?

Quando provo a confermare la forma senza il campo obbligatorio, l'entità non è editato (che è di destra), ma la finestra è chiusa (che non è giusto!)

Quando riapro la finestra posso vedere il rosso evidenziare il campo richiesto (e non valido).

Quello che voglio è impedire la chiusura della finestra di dialogo se il modulo non è valido.

Devo scrivere qualche JS o JSF mi aiuterà?

risposta

30

La risposta ajax di PrimeFaces mette un oggetto args nell'ambito che ha una proprietà validationFailed. Potresti semplicemente usarlo.

oncomplete="if (args &amp;&amp; !args.validationFailed) PF('editDialog').hide()" 

(il controllo preliminare args è necessario non causa un errore di JS quando viene generata un'eccezione durante la richiesta)

Si potrebbe refactoring di una funzione riutilizzabile JS come segue.

oncomplete="hideDialogOnSuccess(args, 'editDialog')" 
function hideDialogOnSuccess(args, dialogWidgetVar) { 
    if (args && !args.validationFailed) { 
     PF(dialogWidgetVar).hide(); 
    } 
} 
2

Credo che questa sia la soluzione più pulita. In questo modo si non è necessario modificare il codice dei tasti. Questa soluzione sostituisce il prototipo della funzione Nascondi.

$(document).ready(function() { 
    PrimeFaces.widget.Dialog.prototype.originalHide = PrimeFaces.widget.Dialog.prototype.hide; // keep a reference to the original hide() 
    PrimeFaces.widget.Dialog.prototype.hide = function() { 
     var ajaxResponseArgs = arguments.callee.caller.arguments[2]; // accesses oncomplete arguments 
     if (ajaxResponseArgs && ajaxResponseArgs.validationFailed) { 
      return; // on validation error, prevent closing 
     } 
     this.originalHide(); 
    }; 
}); 

In questo modo, è possibile mantenere il codice come:

<p:commandButton value="Save" oncomplete="videoDetalheDialogJS.hide();" 
    actionListener="#{videoBean.saveVideo(video)}" /> 
+0

Come è "il più pulito"? Stai raccomandando una funzione a 11 righe su un'opzione per aggiungere semplicemente un controllo variabile facilmente disponibile? – kolossus

+0

beh, ci vediamo punto .. ma la cosa qui è fare un "nascondiglio trasparente"; Voglio dire ... tu fai sempre un nascondiglio normale() indipendentemente dal fatto che sia convalidato o meno (piuttosto che testare qualche volta); chiedi di nascondere ovunque come: oncomplete = "editDialog.hide()" e non preoccuparti se la convalida fallirà o meno; sarà gestito "sotto" ... –

0

per mantenere la finestra di dialogo Apri sulla convalida non riuscita, è sufficiente impostare la commandButton come segue:

<p:commandButton value="save" 
action="#{YourBean.yourActionMethod}" 
oncomplete="if (!args.validationFailed) PF('yourDialogWidgetVar').hide()"/> 

I lascerò qui un esempio completo:

<h:form id="ad-form"> 
      <p:dialog id="ad-dialog" widgetVar="adDialog" modal="true" width="400" 
      closeOnEscape="true" resizable="false" header="Addreass"> 

      <p:messages id="a-msgs" closable="true" /> 

      <h:panelGrid columns="2" id="ad-painel-dialog" width="100%"> 
       <p:outputLabel value="Country" for="country" /> 
       <p:inputText id="country" style="width:100%" 
        value="#{clientSaverBean.editableAddress.country}" /> 

       <p:outputLabel value="City" for="city" /> 
       <p:inputText id="city" 
        value="#{clientSaverBean.editableAddress.city}" /> 

       <p:outputLabel value="Zip-Code" for="zipcode" /> 
       <p:inputText id="zipcode" 
        value="#{clientSaverBean.editableAddress.zipCode}" /> 

       <p:outputLabel value="Street" for="street" /> 
       <p:inputTextarea id="street" 
        value="#{clientSaverBean.editableAddress.street}" /> 

       <p:outputLabel value="Number" for="number" /> 
       <p:inputText id="number" 
        value="#{clientSaverBean.editableAddress.number}" /> 

       <h:panelGroup /> 

       <f:facet name="footer"> 
        <p:commandButton value="save" 
         action="#{clientSaverBean.saveAddress}" 
         process=":ad-form:ad-dialog" 
         update=":ad-form:a-msgs :ad-form:ad-painel-dialog :client-form:ad-table" 
         oncomplete="if (!args.validationFailed) PF('adDialog').hide()"/> 
       </f:facet> 
      </h:panelGrid> 
     </p:dialog> 

    </h:form> 
+4

Perché stai ripetendo una risposta già data? – BalusC

4

questo post ha ora tre anni, ma ho trovato utile, quindi i miei risultati possono aiutare gli altri.

In PF 5.x almeno, sembra che la soluzione fornita da BalusC debba essere modificata in due modi. (1) aggiungere l'argomento "args" alla chiamata in caso di evento oncompleto e (2) utilizzare la primitiva PF primefaces per identificare il widget nelle tabelle PF.Ecco il codice che sto usando:

oncomplete="hideDialogOnSuccess(args, PF('editDialog'))" 

function hideDialogOnSuccess(args, dialogWidgetVar) { 
    if (args && !args.validationFailed) { 
     dialogWidgetVar.hide(); 
    } 
} 
+0

Non ottieni molta reputazione, ma puoi, suggerire modifiche alla buona risposta accettata. Invece si guadagna la reputazione e l'apprezzamento del "mondo reale" allora ;-) mai meno ... entrambi svitati – Kukeltje

+0

BalusC ha aggiornato la sua risposta, quindi il mio è ora irrilevante. Guarda il suo. – LaurentV

+0

ha già fatto prima ho commentato qui (guardando il timestamp) Scusa ... Grazie comunque per aver scoperto e condiviso – Kukeltje