Search code examples
jsfbootsfaces

Validation of a b:modal form is not working


I am trying to validate a modal form ( JSF/Bootsfaces ) and prevent it from being saved if the inputtext is not correct. For some reason I ignore it is not working, here is the JSF code:

    <b:modal id="creation"
             title="#{msgs['page.manageFlights.addingNew']}"
             styleClass="formValidationModalClass"
             closeOnEscape="false"
             backdrop="false"
             closable="false">

        <b:form id="createModal">
            <b:selectOneMenu
                    value="#{flightBean.currentFlight.journey}"
                    label="#{msgs['page.manageFlights.findAllJourneys']}"
                    required="true"
                    requiredMessage="Please select a journey"
                    large-screen="full-width">
                <f:selectItems value="#{journeyBean.findAllJourneys()}" var="journey" itemValue="#{journey}" itemLabel="#{journey.departureLocation} -> #{journey.arrivalLocation}" />

            </b:selectOneMenu>
            <b:dateTimePicker
                    value="#{flightBean.currentFlight.departureDate}"
                    label="#{msgs['page.manageFlights.departureDate']}"
                    required="true"
                    requiredMessage="Please enter a date and time"
                    large-screen="full-width">
            </b:dateTimePicker>

            <b:dateTimePicker
                    value="#{flightBean.currentFlight.arrivalDate}"
                    label="#{msgs['page.manageFlights.arrivalDate']}"
                    required="true"
                    requiredMessage="Please enter a date and time"
                    large-screen="full-width">
            </b:dateTimePicker>

            <b:inputText     value="#{flightBean.currentFlight.numberOfBusinessClassSeats}"
                             label="#{msgs['page.manageFlights.numberOfBusinessClassSeats']}"
                             required="true"
                             requiredMessage="The number of seats must be positive"
                             large-screen="full-width">
                <f:validateLongRange minimum = "1" maximum = "2000" />
            </b:inputText>
            <b:inputText
                    value="#{flightBean.currentFlight.numberOfEconomyClassSeats}"
                    label="#{msgs['page.manageFlights.numberOfEconomyClassSeats']}"
                    required="true"
                    requiredMessage="Please enter a number"
                    validatorMessage="The number of seats must be positive"
                    large-screen="full-width">
            </b:inputText>
            <br/>
            <b:row>
                <b:column>
                    <b:commandButton
                            largeScreen="half"
                            value="#{msgs['cancel.button']}"
                            dismiss="modal"
                            action="#{flightBean.resetCurrentFlight()}"
                            oncomplete="$('#creation').modal('hide')"
                    />
                    <b:commandButton
                            largeScreen="half"
                            dismiss="modal"
                            update="@(#dataTable)"
                            value="#{msgs['save.button']}" look="success"
                            action="#{flightBean.addFlight(flightBean.currentFlight)}"
                            oncomplete="if(!validationFailed) { $('#creation').modal('hide')};">
                    </b:commandButton>
                </b:column>
            </b:row>
            <b:fetchBeanInfos/>
            <b:messages/>
        </b:form>
    </b:modal>

I am trying to check if the number of business class seats is positive. As you can see I added fetchbeaninfos, validateLongRange and oncomplete.


Solution

  • <b:fetchBeanInfos> and validationFailed only work after an AJAX request. You need to send the input to the server, have it validated there, and only when the response is sent back to the client, validationFailed is updated.

    My suggestion is to use simple JavaScript to show the error message and to disable the button.

    However, if you prefer to use server-side validation, here's what to do:

    • Add an empty validateInput() method to your bean. It doesn't need any implementation; it just has to be there so it can be called by an JSF AJAX call.
    • Add an id to <b:fetchBeanInfos>.
    • Add an AJAX change listener to each input field. Depending on the type of the input field, you may need a different listener (onblur, onchange, etc.), but the general idea is like so:

      <b:inputText
                  onblur="ajax:flightBean.validateInput()"
                  update="**:fetchBeansId"
                  value="..."
                  label="..."
                  required="true"
                  requiredMessage="..."
                  validatorMessage="...">
      </b:inputText>
      <b:fetchBeanInfos id="fetchBeansId"/>
      

    The **:idbit helps you if your JSF page has multiple "namespaces", such as forms, modals, data tables, and tabs. These namespaces add a prefix to the id, and **:id allows you to find the id no matter what the prefix is.