JSF复杂形式 - 绑定错误

时间:2011-03-09 17:20:43

标签: jsf jsf-2

我的表单包含一些输入,后面有 ViewScoped * ManagedBean *。在表单的底部,我有一个用于保存数据的CommandButton。表单上有一个数据表,可以通过将数据输入到输入并单击另一个 CommandButton 来添加新项目。当用户填写所有输入并将任何项添加到数据表时,他/她可以单击保存按钮。但是我在控制添加按钮和更新数据模型时遇到了一些问题。当我将按钮的 immadiate 设置为true时,输入的值将不会更新,当我将其设置为false时,验证错误将发生在表单上的其余输入!!! / p>

代码如果有帮助:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
                template="./templates/master.xhtml"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:p="http://primefaces.prime.com.tr/ui"
                xmlns="http://www.w3.org/1999/xhtml">

  <ui:define name="windowTitle">
    #{lbls.registerWaggon}
  </ui:define>

  <ui:define name="sectionTitle">
    <h:panelGroup layout="block" styleClass="sectionTitle">
      <h:graphicImage library="img" name="railways.png"/>
    </h:panelGroup>
  </ui:define>

  <ui:define name="right">
    <ui:include src="templates/railwaysright.xhtml"/>
  </ui:define>

  <ui:define name="extraCSS">
    <h:outputStylesheet library="css" name="persiancalendar.css"/>
    <h:outputStylesheet library="css" name="grid.css"/>
  </ui:define>

  <ui:define name="extraJS">
    <h:outputScript library="js" name="lib/persiancalendar.js"/>
  </ui:define>

  <ui:define name="content">
    <h:panelGroup rendered="#{!current.hasLoggedIn()}">      
      <h:panelGroup layout="block" styleClass="warningBox">
        <h:outputText value="#{app.youHaveNotLoggedIn}"/>
        <br/>
        <h:link value="#{lbls.login}" outcome="login"/>
      </h:panelGroup>      
    </h:panelGroup>


    <p:panel rendered="#{current.hasLoggedIn() and requestWaggon.isViewable()}">
      <f:facet name="header">
        <h:outputText value="#{lbls.registerWaggonLong}" />
      </f:facet>

      <h:form id="frmRequest">
        <h:panelGrid columns="3" footerClass="buttons">
          <h:outputText value="#{lbls.number}:"/>
          <h:inputText id="number" label="#{lbls.number}" styleClass="ltr" value="#{requestWaggon.request.number}" readonly="true" />
          <h:message for="number" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>

          <h:outputText value="#{lbls.requestDate}:"/>
          <h:inputText styleClass="ltr" id="date" label="#{lbls.requestDate}" value="#{requestWaggon.request.date}" required="true" readonly="true">
            <f:converter converterId="ir.khorasancustoms.DateConverter"/>
          </h:inputText>          
          <h:message for="date" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>

          <h:outputText value="#{lbls.nameOfMaterialOwner}:"/>
          <h:inputText id="ownerName" label="#{lbls.nameOfMaterialOwner}" value="#{requestWaggon.request.fullName}" required="true" readonly="true"/>
          <h:message for="ownerName" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>

          <h:outputText value="#{lbls.companyName}:"/>
          <h:inputText id="companyName" label="#{lbls.companyName}" value="#{requestWaggon.request.companyName}" required="true" readonly="true"/>
          <h:message for="companyName" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>

          <h:outputText value="#{lbls.nameOfMaterial}:"/>
          <h:inputText id="nameOfMaterial" label="#{lbls.nameOfMaterial}" value="#{requestWaggon.request.materialName}" required="true" readonly="true"/>
          <h:message for="nameOfMaterial" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>                        

          <h:outputText value="#{lbls.materialWeight}:"/>
          <h:panelGroup>
            <h:inputText id="materialWeight" styleClass="ltr" label="#{lbls.materialWeight}" value="#{requestWaggon.request.materialWeight}" required="true" style="min-width: 0px; width: 60px" readonly="true"/>
            <h:outputText value=" #{requestWaggon.request.weightUnit}"/>            
          </h:panelGroup>
          <h:message for="materialWeight" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>

          <h:outputText value="#{lbls.senderAddress}:"/>
          <h:inputText id="senderAddress" label="#{lbls.senderAddress}" value="#{requestWaggon.request.address}" required="true" style="width: 350px;" readonly="true"/>
          <h:message for="senderAddress" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>

          <h:outputText value="#{lbls.receiverAddress} (#{lbls.country}):"/>            
          <h:outputText value="#{requestWaggon.request.country}"/>
          <h:message for="country" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>

          <h:outputText value="#{lbls.station}:"/>
          <h:inputText id="station" label="#{lbls.station}" value="#{requestWaggon.request.station}" required="true" readonly="true"/>
          <h:message for="station" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>

          <h:outputText value="#{lbls.loadingDate}:"/>
          <h:panelGroup>
            <h:inputText styleClass="ltr" id="loadingDate" label="#{lbls.loadingDate}" value="#{requestWaggon.request.loadingDate}" required="true" readonly="true">
              <f:converter converterId="ir.khorasancustoms.DateConverter"/>
            </h:inputText>            
          </h:panelGroup>
          <h:message for="loadingDate" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>

          <h:outputText value="#{lbls.boundryStation}:"/>            
          <h:outputText value="#{requestWaggon.request.bountryStation}"/>
          <h:message for="boundryStation" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>

          <h:outputText value=""/>
          <h:outputText value=""/>
          <h:outputText value=""/>

          <h:outputText value="#{lbls.confirmDate}:"/>
          <h:panelGroup>
            <h:inputText styleClass="date ltr" id="confirmDate" label="#{lbls.confirmDate}" value="#{requestWaggon.request.confirmDate}" required="true">
              <f:converter converterId="ir.khorasancustoms.DateConverter"/>
            </h:inputText>
            <input type="button" value="..." onclick="displayDatePicker('frmRequest:confirmDate', this);" class="datePicker"/>
          </h:panelGroup>
          <h:message for="confirmDate" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>

          <h:outputText value="#{lbls.confirm}:" styleClass="b"/>
          <h:selectOneMenu value="#{requestWaggon.request.confirm}">
            <f:selectItem/>
            <f:selectItems value="#{searchRequest.allConfirms}" var="confirm" itemLabel="#{searchRequest.confirmCaption(confirm)}" itemValue="#{confirm}"/>
          </h:selectOneMenu>
          <h:message for="confirm" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>

          <h:outputText value="#{lbls.description}:"/>
          <h:inputText id="description" label="#{lbls.description}" value="#{requestWaggon.request.confirmDescription}" required="false" style="width: 350px;"/>
          <h:message for="description" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>

          <h:outputText value="#{lbls.waggonType}:"/>            
          <h:selectOneMenu id="waggonType" label="#{lbls.waggonType}" value="#{requestWaggon.request.waggonType}" required="true">
            <f:selectItem/>
            <f:selectItems value="#{requestWaggon.waggonTypes}"/>
            <f:converter converterId="ir.khorasancustoms.CatalogValueFixedConverter"/>
          </h:selectOneMenu>            
          <h:message for="waggonType" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>

          **<h:outputText value="#{lbls.specialWaggonNumber}:"/>
          <h:panelGroup>
            <h:inputText id="specialWaggonNumber" label="#{lbls.specialWaggonNumber}" binding="#{requestWaggon.waggonNumberComponent}" />
            <h:commandButton value="#{lbls.add}" action="#{requestWaggon.addWaggon}" immediate="true"/>          
          </h:panelGroup>
          <h:message for="specialWaggonNumber" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>**

          <h:outputText value="#{lbls.waggons}:"/>
          <h:dataTable value="#{requestWaggon.waggonsDataModel}" var="waggon" columnClasses="index,,action" styleClass="grid" headerClass="title" rowClasses="two,three,one">
            <h:column>
              <f:facet name="header">#{lbls.index}</f:facet>
              <h:outputText value="#{searchRequest.datamodel.rowIndex + 1}"/>
            </h:column>
            <h:column>
              <f:facet name="header">#{lbls.number}</f:facet>
              <h:outputText value="#{waggon.number}"/>
            </h:column>
            <h:column>
            <f:facet name="header">#{lbls.action}</f:facet>            
              <h:commandLink action="delete">
                <h:graphicImage styleClass="nb" alt="#{lbls.delete}" title="#{lbls.delete}" library="img" name="delete.png"/>
                <f:param name="id" value="#{waggon.id}"/>
              </h:commandLink>
            </h:column>
          </h:dataTable>

          <f:facet name="footer">
            <h:button outcome="searchrequest" value="#{lbls.cancel}" rendered="#{requestWaggon.id ne null}"/>
            <h:commandButton action="#{requestWaggon.doNew}" value="#{lbls.new}" rendered="#{requestWaggon.request.id ne null}"/>
            <h:commandButton action="#{requestWaggon.save}" value="#{lbls.ok}"/>
          </f:facet>
        </h:panelGrid>
        <h:outputScript>
          focusElement('frmRequest:confirmDate');            
        </h:outputScript>
      </h:form>

      <f:facet name="footer">
        <h:messages styleClass="boxMessages" layout="table" infoClass="infoBox" warnClass="warningBox" errorClass="errorBox" fatalClass="errorBox" globalOnly="true"/>
        <h:link outcome="searchrequest" value="#{lbls.searchRequestWaggon}"/>
      </f:facet>
    </p:panel>    

    <p:panel rendered="#{current.hasLoggedIn() and !requestWaggon.isViewable()}">
      <h:panelGroup layout="block" styleClass="warningBox">
        <h:outputText value="#{app.accessDenied}" />
      </h:panelGroup>
    </p:panel>
  </ui:define>

</ui:composition>

@ManagedBean(name = "requestWaggon")
@ViewScoped
public class RequestWaggonBean {
  //<editor-fold defaultstate="collapsed" desc="FIELDS">

  private Logger logger;
  @ManagedProperty(value = "#{current}")
  private CurrentSessionBean current;
  private RequestWaggon request;
  private Set<CatalogValue> weightUnits;
  private Set<CatalogValue> countries;
  private Set<CatalogValue> boundryStations;
  private Set<CatalogValue> waggonTypes;
  private Integer id;
  @ManagedProperty(value = "#{searchRequest}")
  private SearchRequestBean searchRequest;
  private Integer newWaggonNumber;  
  private HtmlInputText waggonNumberComponent;
  private DataModel<Waggon> waggonsDataModel;
  //</editor-fold>

  //<editor-fold defaultstate="collapsed" desc="CONSTRUCTORS">
  public RequestWaggonBean() {
    logger = LogUtil.getLogger(RequestWaggonBean.class);
    request = new RequestWaggon();    

    ExternalContext exContext = FacesContext.getCurrentInstance().getExternalContext();
    HttpServletRequest httpRequest = (HttpServletRequest) exContext.getRequest();
    String strId = httpRequest.getParameter("id");
    try {
      id = Integer.parseInt(strId);
    } catch (Exception ex) {
      logger.fatal(ex);
    }
  }

  @PostConstruct
  public void init() {
    request.setDate(current.getDate());

    SessionFactory factory = new Configuration().configure().buildSessionFactory();
    Session session = factory.openSession();
    ResourceBundle app = ResourceBundle.getBundle("application");
    try {
      //session.beginTransaction();

      if (id != null) {
        request = (RequestWaggon) session.get(RequestWaggon.class, id);
      }

      Query query = session.createQuery("from CatalogGroup as catalogGroup where catalogGroup.englishTitle = :englishTitle");
      query.setParameter("englishTitle", "WeightUnit");
      CatalogGroup weightUnit = (CatalogGroup) query.uniqueResult();
      weightUnits = weightUnit.getValues();

      query.setParameter("englishTitle", "Country");
      CatalogGroup country = (CatalogGroup) query.uniqueResult();
      countries = country.getValues();

      query.setParameter("englishTitle", "BoundryStation");
      CatalogGroup boundryStation = (CatalogGroup) query.uniqueResult();
      boundryStations = boundryStation.getValues();

      query.setParameter("englishTitle", "WaggonType");
      CatalogGroup waggonType = (CatalogGroup) query.uniqueResult();
      waggonTypes = waggonType.getValues();

      //session.getTransaction().commit();
    } catch (Exception ex) {
      logger.fatal(ex);
      Transaction tx = session.getTransaction();
      if (tx.isActive()) {
        tx.rollback();
      }
      String message = app.getString("databaseConnectionFailed");
      FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, message, message));
    } finally {
      session.close();
    }

    Waggon[] arrayWaggons = new Waggon[request.getWaggons().size()];
    arrayWaggons = request.getWaggons().toArray(arrayWaggons);
    waggonsDataModel = new ArrayDataModel<Waggon>(arrayWaggons);
  }
  //</editor-fold>

  //<editor-fold defaultstate="collapsed" desc="METHODS">
  public void save() {
    boolean canSave = false;
    String cantSaveMessage = "";

    SessionFactory factory = new Configuration().configure().buildSessionFactory();
    Session session = factory.openSession();
    ResourceBundle app = ResourceBundle.getBundle("application");
    try {
      session.beginTransaction();

      int number = 0;
      if (request.getNumber() == null) {
        number = RequestWaggon.nextNumber();
      }

      if (request.getNumber() != null || number > 0) {
        if (request.getNumber() == null) {
          request.setNumber(number);
          canSave = isInsertable();
          cantSaveMessage = app.getString("insertDenied");
        } else {
          canSave = isEditable();
          cantSaveMessage = app.getString("editDenied");
        }

        if (canSave) {
          session.saveOrUpdate(request);

          RequestWaggonHistory history = new RequestWaggonHistory(request, current.getUser(), number > 0 ? 'I' : 'U', current.getIP());
          session.save(history);

          session.getTransaction().commit();

          String message = app.getString("savedSuccessfully");
          FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, message, message));
        } else {
          FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, cantSaveMessage, cantSaveMessage));
        }
      } else {
        logger.fatal("Getting next number failed!");
        String message = app.getString("databaseConnectionFailed");
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, message, message));
      }
    } catch (Exception ex) {
      logger.fatal(ex);
      Transaction tx = session.getTransaction();
      if (tx.isActive()) {
        tx.rollback();
      }
      String message = app.getString("databaseConnectionFailed");
      FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, message, message));
    } finally {
      session.close();
    }
  }

  public void addWaggon(ValueChangeEvent event) {    
    ResourceBundle app = ResourceBundle.getBundle("application");
    String strNewWaggonNumber = event.getNewValue().toString();
    Integer newWaggonNumber = Integer.parseInt(strNewWaggonNumber);
    if (newWaggonNumber == null || newWaggonNumber <= 0) {
      String message = app.getString("EnterWaggonNumber");
      FacesContext.getCurrentInstance().addMessage("frmRequest:specialWaggonNumber", new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message));
    } else {
      Waggon newWaggon = new Waggon();
      newWaggon.setNumber(newWaggonNumber);
      request.getWaggons().add(newWaggon);

      Waggon[] arrayWaggons = new Waggon[request.getWaggons().size()];
      arrayWaggons = request.getWaggons().toArray(arrayWaggons);
      waggonsDataModel = new ArrayDataModel<Waggon>(arrayWaggons);
    }
  }

  public boolean isViewable() {
    return current.isViewable();
  }

  public boolean isDeletable() {
    return current.isDeletable() && request.getWaggons().isEmpty();
  }

  public boolean isInsertable() {
    return current.isInsertable();
  }

  public boolean isEditable() {
    return current.isEditable() && request.getConfirm() == null;
  }

  public void doNew() {
    request = new RequestWaggon();
    request.setDate(current.getDate());
  }

  public String delete() {
    SessionFactory factory = new Configuration().configure().buildSessionFactory();
    Session session = factory.openSession();
    ResourceBundle app = ResourceBundle.getBundle("application");
    try {
      session.beginTransaction();

      session.delete(request);

      RequestWaggonHistory history = new RequestWaggonHistory(request, current.getUser(), 'D', current.getIP());
      session.save(history);

      session.getTransaction().commit();

      searchRequest.search();
      String message = app.getString("deletedSuccessfully");
      FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, message, message));
    } catch (ConstraintViolationException ex) {
      String message = app.getString("constraintViolation");
      FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, message, message));
    } catch (Exception ex) {
      logger.fatal(ex);
      Transaction tx = session.getTransaction();
      if (tx.isActive()) {
        tx.rollback();
      }
      String message = app.getString("databaseConnectionFailed");
      FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, message, message));
    } finally {
      session.close();
    }

    return "searchrequest";
  }
  //</editor-fold>

  //<editor-fold defaultstate="collapsed" desc="PROPERTIES">
  public RequestWaggon getRequest() {
    return request;
  }

  public void setRequest(RequestWaggon requestWaggon) {
    this.request = requestWaggon;
  }

  public CurrentSessionBean getCurrent() {
    return current;
  }

  public void setCurrent(CurrentSessionBean current) {
    this.current = current;
  }

  public Set<CatalogValue> getWeightUnits() {
    return weightUnits;
  }

  public void setWeightUnits(Set<CatalogValue> weightUnits) {
    this.weightUnits = weightUnits;
  }

  public Logger getLogger() {
    return logger;
  }

  public void setLogger(Logger logger) {
    this.logger = logger;
  }

  public Set<CatalogValue> getCountries() {
    return countries;
  }

  public void setCountries(Set<CatalogValue> countries) {
    this.countries = countries;
  }

  public Set<CatalogValue> getBoundryStations() {
    return boundryStations;
  }

  public void setBoundryStations(Set<CatalogValue> boundryStations) {
    this.boundryStations = boundryStations;
  }

  public Integer getId() {
    return id;
  }

  public void setId(Integer id) {
    this.id = id;
  }

  public SearchRequestBean getSearchRequest() {
    return searchRequest;
  }

  public void setSearchRequest(SearchRequestBean searchRequest) {
    this.searchRequest = searchRequest;
  }

  public Set<CatalogValue> getWaggonTypes() {
    return waggonTypes;
  }

  public void setWaggonTypes(Set<CatalogValue> waggonTypes) {
    this.waggonTypes = waggonTypes;
  }

  public Integer getNewWaggonNumber() {
    return newWaggonNumber;
  }

  public void setNewWaggonNumber(Integer newWaggonNumber) {
    this.newWaggonNumber = newWaggonNumber;
  }

  public DataModel<Waggon> getWaggonsDataModel() {
    return waggonsDataModel;
  }

  public void setWaggonsDataModel(DataModel<Waggon> waggonsDataModel) {
    this.waggonsDataModel = waggonsDataModel;
  }    

  public HtmlInputText getWaggonNumberComponent() {
    return waggonNumberComponent;
  }

  public void setWaggonNumberComponent(HtmlInputText waggonNumberComponent) {
    this.waggonNumberComponent = waggonNumberComponent;
  }
  //</editor-fold>
}

1 个答案:

答案 0 :(得分:2)

h:commandButton提交整个表单,所有元素都将被验证。您可以使用ajax进行部分提交。请尝试以下方法:

为您的数据表赋予一个id值。所以你可以从commandButton中引用它:

<h:panelGroup id="tableWrapper">
<h:datatable id="mytable" value="#{requestWaggon.waggonsDataModel}" ..>
       ...
</h:datatable>
</h:panelGroup>

然后在你的commandButton中放一个&lt; f:ajax>renderexecute属性必须包含数据表的ID;不需要immediate=true

<h:commandButton value="#{lbls.add}" action="#{requestWaggon.addWaggon}">
  <f:ajax render="tableWrapper" execute="mytable"/>
</h:commandButton>