首页 > 解决方案 > two date fields - one loses its value, the other works

问题描述

I have a form with two date input fields. The first field named dateFrom always loses its value at page reload while the second one named dateTo works perfectly. When I fill both fields, both values are passed to the UI Bean, and both are successfully used to filter the view (a list of items). The UI Bean stores both values in a statusObject with session scope.

But after the page was updated, only dateTo is still filled while dateFrom one is empty. I've added some System.out.println()'s to the getters and settes of the values to see what happens and both setters are called with a value, then both getters return a value. The dateFrom field just ignores the value it gets from the UI Bean.

I'm using the date field provided by the browser, hence the a:type="date".

The page looks like this:

<?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:a="http://xmlns.jcp.org/jsf/passthrough"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
<h:head/>

<h:body>
  <ui:composition>

    <f:loadBundle basename="de.myapp.Resources" var="bundle"/>

<!-- Some stuff removed for readability -->

    <h:form enctype="multipart/form-data" id="filterForm">
      <div class="filterBar">
        <div class="filterElement">
          <h:inputText a:type="date" id="dateFrom" size="8" maxlength="10"
                       value="#{myBean.dateFrom}"
                       converter="dateConverter"/>
        </div>
        <div class="filterElement">
          <h:inputText a:type="date" id="dateTo" size="8" maxlength="10"
                       value="#{myBean.dateTo}"
                       converter="dateConverter"/>
        </div>
      </div>
      <div class="filterElement">
        <h:commandButton id="refreshButton"
                         action="#{myBean.refreshList}"
                         value=" #{bundle.refresh}"/>
      </div>

    </h:form>

<!-- Some more stuff removed for readability -->

  </ui:composition>
</body>
</html>

I've checked that the words dateFrom and dateTo do not occur in the parts of the page I've removed.

Getters and setters in the UI Bean

public Date getDateFrom() {
  System.out.println("getDateFrom() -> " + statusObjet.getDateFrom());
  return statusObjet.getDateFrom();
}

public void setDateFrom(final Date dateFrom) {
  if (dateFrom != null) {
    System.out.println("setDateFrom( " + dateFrom + " )");
  } else  {
    System.err.println("setDateFrom( NULL )"); // my IDE shows this colored red in the console
  }
  statusObjet.setDateFrom(dateFrom);
}

public Date getDateTo() {
  System.out.println("getDateTo() -> " + statusObjet.getDateTo());
  return statusObjet.getDateTo();
}

public void setDateTo(final Date dateTo) {
  if (dateTo != null) {
    System.out.println("setDateTo( " + dateTo + " )");
  } else {
    System.err.println("setDateTo( NULL )"); // my IDE shows this colored red in the console
  }
  statusObjet.setDateTo(dateTo);
}

Except the ID and the value EL, both fields are identical. Getters and setters are also identical (i've double-checked it). In fact, all the code for dateTo is a copy of dateFrom, that was changed in the editor after copying (replace all in selection).

Why does dateTo work but dateFrom doesn't ?

标签: jsfdatefield

解决方案


It turned out that the problem was not the date field, but the entered date (and a flaw in the dateConverter):

I've always tested the form using Jan 1st and Dec 31st of the same year.

Knowing that the browser-provided date input uses a date format depending on browser language rather than web site language, I've written a dateConverter that understands the most important formats, all of them with and without leading zeroes for one-digit values.
The flaw was that it's getAsString() returned a date format without leading zeroes, and the browser did not understand e.g. 2019-1-1.

Solution: Use a separate DateFormat that forces leading zeroes for getAsString() and return 2019-01-01.


推荐阅读