How can I prevent the jQuery UI look'n'feel from disappearing after form submits/postbacks?

匿名 (未验证) 提交于 2019-12-03 02:38:01

问题:

I have a JSF (Mojarra) v2.1.11, Primefaces v3.4.2, Java 6 web application using jQuery datepicker. I am using a selector that looks similar to this:

$('#form1\\:dp').datepicker({showOn: 'button', buttonText: "Choose"}); 

This enables the user to click the button in order to invoke the datepicker. The issue I'm having is that the "button" disappears after the user submits the form. Apparently, the "button" loads only once when the page is initially loaded. I'd like to know how (what the best practice is) to persist the JQuery datepicker "button" between submits/postbacks.

index.xhtml

<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"       xmlns:ui="http://java.sun.com/jsf/facelets"       xmlns:h="http://java.sun.com/jsf/html"       xmlns:f="http://java.sun.com/jsf/core"       xmlns:c="http://java.sun.com/jsp/jstl/core"       xmlns:p="http://primefaces.org/ui">     <f:view contentType="text/html">         <h:head>             <title>testcal - index.xhtml</title>             <meta charset="utf-8" />         </h:head>         <h:body>             <h:form id="queryForm">                 <f:event type="postValidate" listener="#{testBean.validate}" />                 <p:panel id="queryPanel"  header="Test p:calendar, datepicker, validation, etc..." style="width:100%;">                      <p:focus context="queryPanel"/>                      <h:panelGroup id="msgs">                         <p:message id="lastName_msg"    for="lastName"     style="display:none;"/>                         <p:message id="birthDate_msg"   for="birthDate"    style="display:none;"/>                         <p:message id="startDate_msg"   for="startDate"    style="display:none;"/>                         <p:message id="endDate_msg"      for="endDate"     style="display:none;"/>                         <p:message id="drpdwn_msg"       for="drpdwn"      style="display:none;"/>                     </h:panelGroup>                     <br/>                     <br/>                     <h:panelGroup id="querypanelgroup" style="display:inline-block;">                         <p:focus context="querypanelgroup"/>                          <h:panelGroup>                             <h:panelGroup style="text-align:right;vertical-align:middle;display:inline-block;width:150px">                                 <p:outputLabel style="margin-right: 5px;"  value="Last Name:" for="lastName"/>                             </h:panelGroup>                             <h:panelGroup style="margin-left: 4px; vertical-align:middle;display:inline-block;width:250px;">                                 <p:inputText                                     id="lastName"                                     value="#{testBean.parmMap['lastName']}"                                     requiredMessage="last name required"                                     size="95"                                     maxlength="95"                                     onfocus="$('#queryForm\\:msgs > div').hide();$('#queryForm\\:msgs > div').eq(0).show();return false;" >                                 </p:inputText>                             </h:panelGroup>                         </h:panelGroup>                          <br/>                         <br/>                          <h:panelGroup>                             <h:panelGroup style="text-align:right;vertical-align:middle;display:inline-block;width:150px">                                 <p:outputLabel style="margin-right: 5px;"  value="Birth Date:" for="birthDate"/>                             </h:panelGroup>                             <h:panelGroup style="margin-left: 4px; vertical-align:middle;display:inline-block;width:250px;">                                 <p:inputText                                     id="birthDate"                                     value="#{testBean.parmMap['birthDate']}"                                     requiredMessage="birth date required"                                     converter="dpConverter"                                     styleClass="datePicker"                                     onfocus="$('#queryForm\\:msgs > div').hide();$('#queryForm\\:msgs > div').eq(1).show();$(this).mask('99/99/9999');return false;">                                     <p:ajax event="change" process="@this" update="@this"/>                                 </p:inputText>                             </h:panelGroup>                         </h:panelGroup>                          <br/>                         <br/>                          <h:panelGroup>                             <h:panelGroup style="text-align:right;vertical-align:middle;display:inline-block;width:150px">                                 <p:outputLabel style="margin-right: 5px;"  value="Start Date:" for="startDate"/>                             </h:panelGroup>                             <h:panelGroup style="margin-left: 4px; vertical-align:middle;display:inline-block;width:250px;">                                 <p:inputText                                     id="startDate"                                     value="#{testBean.parmMap['startDate']}"                                     requiredMessage="start date required"                                     converter="dpConverter"                                     styleClass="datePicker"                                     onfocus="$('#queryForm\\:msgs > div').hide();$('#queryForm\\:msgs > div').eq(2).show();$(this).mask('99/99/9999');return false;">                                     <!-- optional to populate another field with same value...                                     onchange="$('...hashSymbolHere...queryForm\\:endDate').val($(this).val());">                                     -->                                     <p:ajax event="change" process="@this" update="@this"/>                                 </p:inputText>                             </h:panelGroup>                         </h:panelGroup>                          <br/>                         <br/>                          <h:panelGroup>                             <h:panelGroup style="text-align:right;vertical-align:middle;display:inline-block;width:150px">                                 <p:outputLabel for="endDate" value="Enter a date:"/>                             </h:panelGroup>                             <h:panelGroup style="margin-left: 4px; vertical-align:middle;display:inline-block;width:250px;">                                 <p:inputText                                     id="endDate"                                     value="#{testBean.parmMap['endDate']}"                                     requiredMessage="endDate required"                                     converter="dpConverter"                                     styleClass="datePicker"                                     onfocus="$('#queryForm\\:msgs > div').hide();$('#queryForm\\:msgs > div').eq(3).show();$(this).mask('99/99/9999');return false;">                                     <p:ajax event="change" process="@this" update="@this"/>                                 </p:inputText>                             </h:panelGroup>                         </h:panelGroup>                          <br/>                         <br/>                          <h:panelGroup>                             <h:panelGroup style="text-align:right;vertical-align:middle;display:inline-block;width:150px">                                 <p:outputLabel for="drpdwn" value="Choose from drop down selction:">                                     <h:panelGroup rendered="false"  style="margin-left: 2px;"  id="drpdwnRequired" styleClass="requiredInd">*</h:panelGroup>                                 </p:outputLabel>                             </h:panelGroup>                             <h:panelGroup style="margin-left: 4px; vertical-align:middle;display:inline-block;width:250px;">                                 <p:autoComplete                                     id="drpdwn"                                     style="overflow: hidden"                                     maxResults="200"                                     scrollHeight="150"                                     dropdown="false"                                     value="#{testBean.parmMap['drpdwn']}"                                     completeMethod="#{testBean.drpdwnListComplete}"                                     var="entry"                                     itemLabel="#{entry.split(':')[1]}"                                     itemValue="#{entry.split(':')[0]}"                                     minQueryLength="1"                                     forceSelection="true"                                     onfocus="$('#queryForm\\:msgs > div').hide();$('#queryForm\\:msgs > div').eq(4).show();" >                                 </p:autoComplete>                             </h:panelGroup>                         </h:panelGroup>                          <br/>                         <br/>                          <p:commandButton id="submit" value="Submit" oncomplete="applyDatePicker();" type="submit" update="@form" process="@form" action="#{testBean.submitQuery}" style="width:150px;" styleClass="button"/>                         <p:commandButton value="Reset" update="@form" onclick="location.reload();return true;" process="@this" actionListener="#{testBean.reset}" immediate="true" ajax="false"/>                      </h:panelGroup>                 </p:panel>             </h:form>              <h:outputStylesheet library="styles"    name="query.css"      />             <h:outputScript      library="primefaces" name="/jquery/jquery.js" />             <h:outputScript      library="primefaces" name="/jquery/plugins/ui/jquery-ui.custom.js" />             <h:outputScript     library="primefaces" name="/jquery/plugins/inputmask/maskedinput.js" />             <h:outputScript      library="js" name="testcal2.js" target="head" />           </h:body>     </f:view> </html>  

TestBean.java

package aaa.bbb.ccc.war;  import java.io.IOException; import java.io.Serializable; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import javax.faces.application.FacesMessage; import javax.faces.component.UIForm; import javax.faces.component.UIInput; import javax.faces.component.UIPanel; import javax.faces.context.FacesContext; import javax.faces.event.ActionEvent; import javax.faces.event.ComponentSystemEvent; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component;  @Component("testBean") @Scope("view") public class TestBean implements Serializable {      private static final List<String> drpdwnListOrig;       private static final String[] prfx = {"aaa","bbb","ccc", "ddd", "eee", "fff","ggg","hhh","iii","jjj","kkk","lll","mmm","nnn","ooo","ppp","qqq","rrr","sss","ttt","uuu","vvv","www","xxx","yyy","zzz"};      //////////////////////////// [static initializer] ///////////////////////////////     //////////////////////////// [static initializer] ///////////////////////////////     //////////////////////////// [static initializer] ///////////////////////////////     static     {         //drpdwnListOrig...         List<String> l = getListOfStrings();         drpdwnListOrig = Collections.unmodifiableList(null == l ? new ArrayList<String>() : l);         FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("drpdwnListOrig", drpdwnListOrig);         List<String> testList = (List<String>) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("drpdwnListOrig");     }      public TestBean()     {         parmMap = this.getParmMap();         FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("parmMap", parmMap);     }      public void reset(ActionEvent event)     {         LinkedHashMap<String, Object> m = new LinkedHashMap<String, Object>();         FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("parmMap");         setParmMap(m);     }      public String submitQuery()     {         FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("hitlistData");         if (this.getParmMap().isEmpty())         {             return "";         }          return "/page2.xhtml?faces-redirect=true";     }       private static LinkedHashMap<String, Object> parmMap;     public LinkedHashMap<String, Object> getParmMap()     {         LinkedHashMap<String, Object> map = (LinkedHashMap<String, Object>) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("parmMap");          if (null == map)         {             map = new LinkedHashMap<String, Object>();         }         return map;     }      public void setParmMap(LinkedHashMap<String, Object> map)     {         parmMap = map;         FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("parmMap", parmMap);     }       private static SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");     public void validate(ComponentSystemEvent e) throws ParseException     {          LinkedHashMap parmMap = this.getParmMap();         UIForm queryForm = (UIForm) e.getComponent();          UIInput lastName_c = (UIInput) queryForm.findComponent("lastName");         String lastName = (String) (lastName_c.getValue());         UIInput birthDate_c = (UIInput) queryForm.findComponent("birthDate");         birthDate_c.setValid(true);         String birthDate = (String) birthDate_c.getValue();          FacesContext fc = FacesContext.getCurrentInstance();          if (null != lastName && lastName.trim().length() > 0)         {             birthDate_c.setRequired(true);              if (null == birthDate || birthDate.length() < 1)             {                 birthDate_c.setValid(false);                 fc.addMessage(birthDate_c.getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, "birth date is required", "birth date is required"));                 fc.renderResponse();             }             else             {                 birthDate_c.setValid(true);             }         }         else         {             birthDate_c.setValid(true);             birthDate_c.setRequired(false);         }     }      //////////////////////////// autocomplete ///////////////////////////////         //////////////////////////// autocomplete ///////////////////////////////         //////////////////////////// autocomplete ///////////////////////////////         private static List<String> drpdwnList;      public static List<String> getDrpdwnList()     {         if (null == drpdwnList)         {             drpdwnList = (null == drpdwnList ? (List<String>) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("drpdwnListOrig") : drpdwnListOrig);         }          return drpdwnList;     }     public void setDrpdwnList(List<String> data) throws IOException     {         drpdwnList = data;     }     public static List<String> drpdwnListComplete(String s)       //autocomplete "completeMethod"...     {         List<String> list = getDrpdwnList();         List<String> drpdwnSuggestions = new ArrayList<String>();         for (String ss : list)         {             if (ss.toLowerCase().contains(s.toLowerCase()))             {                 drpdwnSuggestions.add(ss);             }         }         FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("drpdwnSuggestions", drpdwnSuggestions);          return drpdwnSuggestions;     }       //////////////////////////// get listbox values ///////////////////////////////     //////////////////////////// get listbox values ///////////////////////////////     //////////////////////////// get listbox values ///////////////////////////////     public static List<String> getListOfStrings() //(String sql)     {         List<String> list = new ArrayList<String>();          int ii=0;         String key=null;         String val=null;         for (int i=0;i< 3500; i++)         {              if (ii > 25)             {                 ii=0;             }              key = (i + "").trim();             val = (i + prfx[ii]).trim();              list.add(key + ":" + val);               ii++;         }          return list;      }      } 

testcal2.js

$(document).ready(function() {     applyDatePicker(); });   function applyDatePicker(){      $('.datePicker').datepicker(     {         showOn: 'button',          buttonText: "Choose",         showButtonPanel: true,         showOptions: {direction: 'up'},         changeYear: true,         changeMonth: true,         yearRange: "c-120:c+0"     }); } 

回答1:

If I understood you right

place the js code in a function

function applyDatePicker(){  $('#queryForm\\:dp2').datepicker(     {         showOn: 'button',         buttonText: "Choose"     }); } 

Call it in $(document).ready

$(document).ready(function() {    applyDatePicker(); }); 

And also call it in <p:commandButton

<p:commandButton onsuccess="applyDatePicker();"... 


回答2:

The concrete problem is caused because you're updating the whole form by update="@form", causing the jQuery UI-manipulated input element to be re-rendered as well, causing the jQuery UI look'n'feel to be lost. The $(document).ready() is not re-executed on ajax requests and hence the input element remains "plain".

There are basically 2 solutions to this problem:

  1. Do not update the input element itself on ajax response. Update only the parts which really need to be updated. Perhaps it's just only the message?

    update="msgs" 

    (by the way, those rendered="true" and style="display:none" are very strange)

    You can if necessary specify multiple components spaceseparated.

    update="msgs1 msgs2 msgs3" 

    You can also just use autoUpdate="true" on message components which you'd like to automatically update on ajax responses. Or if the component in question doesn't support it, wrap it in <p:outputPanel autoUpdate="true">. See also Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes.


  2. Re-execute the jQuery UI script on complete of ajax request. This part is already answered by Daniel. An alternative to onsuccess is to use OmniFaces' <o:onloadScript>. See also JSF/PrimeFaces ajax updates breaks jQuery event listener function bindings.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!