0
votes

I have a form with some inputs which has a ViewScoped *ManagedBean* behind. At the bottom of the form I have a CommandButton for saving the data. There is a datatable on the form which new items could be added by entering data to an input and clicking another CommandButton. When user filled all the inputs and added any items to the datatable he/she can click the save button. But I have some problems in controling the add button and updating the datamodel. When I set the immadiate of the button to true the value of the input won't update and when I set it to false validation error will happen for the rest of the inputs on the form!!!

Code if it helps:

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

bean

@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

1 Answers

2
votes

The h:commandButton submits the whole form and all elements will be validated. You can use ajax to do a partial submit. Try the following:

Give your datatable an id value. So you can reference it from your commandButton:

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

Then put an <f:ajax> inside your commandButton. The render and execute attributes must contain the id of your datatable; immediate=true is not needed:

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