如何为空输入组件设置自定义非空值 dispite INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL = true
How to have a custom non null value for empty input component dispite INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL = true
在我的faces-config.xml
中我设置了
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
因此,没有输入的任意输入组件将 null
放入绑定到 value="#{myBean.someDate}"
属性的 bean 属性 中,并在从中获取 null
时呈现一个空组件那个豆子 属性.
虽然这通常是应用程序所需的行为,但我有一个特定组件,我想用自定义 non null
值替换 null
。
有什么通用的好方法可以实现吗?
我已经用 Mojarra 2.3.8 为 Primefaces (6.2) 日历试过这个:
<h:form id="myForm">
<p:calendar value="#{myBean.someDate}" pattern="MM/dd/yyyy"
converter="mySpecialDateConverter" locale="en" />
<p:commandButton value="send" process="@form" update="@form" />
<hr />
<h:outputText value="#{myBean.someDate}" />
</h:form>
我尝试使用一个转换器,当从 #{myBean.someDate}
收到我的自定义值时,在 getAsString()
中渲染组件 returns 一个 empty String
,或者吐出我的当提交null
或纯空时getAsObject()
中的自定义值:
import java.util.Date;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.DateTimeConverter;
import javax.faces.convert.FacesConverter;
@FacesConverter("mySpecialDateConverter")
public class MyConverter extends DateTimeConverter {
private static final Date PAST = new Date(0);
public MyConverter() {
setPattern("MM/dd/yyyy");
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (PAST.equals(value)) {
return "";
}
return super.getAsString(context, component, value);
}
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (null == value || "".equals(value.trim())) {
return PAST;
}
return super.getAsObject(context, component, value);
}
}
当 bean 属性 等于 PAST
时呈现空日历组件按预期工作。但是在没有输入的情况下提交日历会将 属性 设置为 null
因为 Primefaces CalendarRenderer
根本不会在提交空白值时参考 Converter
:
package org.primefaces.component.calendar;
public class CalendarRenderer extends InputRenderer {
// ...
public Object getConvertedValue(FacesContext context, UIComponent component, Object value) throws ConverterException {
Calendar calendar = (Calendar) component;
String submittedValue = (String) value;
SimpleDateFormat format = null;
if (isValueBlank(submittedValue)) {
return null;
}
//Delegate to user supplied converter if defined
try {
Converter converter = calendar.getConverter();
if (converter != null) {
return converter.getAsObject(context, calendar, submittedValue);
}
}
// ...
}
// ...
}
这部分没问题,正如 Converter.getAsObject()
上的 JavaDoc 所说:
/**
* @return <code>null</code> if the value to convert is <code>null</code>,
* otherwise the result of the conversion
*/
Primefaces 没有理由在空输入时解析转换器。如果我们设置 javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL = false
,恕我直言,情况会有所不同。然后我认为上述行为不正确,因为 ""
不是 null
.
为了完整起见,这是我的 bean myBean
:
import java.io.Serializable;
import java.util.Date;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
@Named
@ViewScoped
public class MyBean implements Serializable {
private static final long serialVersionUID = 1L;
private Date someDate;
public Date getSomeDate() {
return someDate;
}
public void setSomeDate(Date someDate) {
this.someDate = someDate;
}
}
我不想更改该 bean,因为在实际应用程序中,Calendars 的值绑定到持久实体 属性 值。我也不希望持久层完成这项工作。
非常背景:
我想阻止某些数据库 DATE
字段中的 null
值。例如,在期间的情况下,我希望开始默认为与应用程序上下文无关的某个遥远的过去日期,对于该期间的结束,我想要一个与应用程序上下文无关的遥远未来的日期,并且两者都不会打扰用户哪些日期他们是默认的。这些默认日期有助于过滤当前 Date
在该时间段内或之外的实体,同时假设用户没有输入实际上是在时间段 for ever
.
JSF 组件不会在空值或它们认为为空的任何值上调用转换器 - 这对于 JSF 中的默认组件也是如此。所以在这方面,我猜想 PrimeFaces 的行为符合预期,这是正确的结果。这里有两种立即想到的规避方法;
使用 OmniFaces
如 JSF converter with null value 中所述,OmniFaces o:param
将调用您的转换器而不考虑空值 - 您可以使用它向组件传递参数。在您的具体情况下,您应该能够执行与此类似的操作;
<h:form id="myForm">
<p:calendar value="#{myBean.someDate}" pattern="MM/dd/yyyy" locale="en" />
<p:commandButton value="send" process="@form" update="@form">
<o:param name="date" value="#{myBean.someDateConversion}"
converter="mySpecialDateConverter" />
</p:commandButton>
<hr />
<h:outputText value="#{myBean.someDate}" />
</h:form>
使用自定义渲染器
第二个选项是使用自定义渲染器,只需修改组件的行为以始终调用转换器,如此答案中所述 - JSF Custom Converter not called on null value。
在我的faces-config.xml
中我设置了
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
因此,没有输入的任意输入组件将 null
放入绑定到 value="#{myBean.someDate}"
属性的 bean 属性 中,并在从中获取 null
时呈现一个空组件那个豆子 属性.
虽然这通常是应用程序所需的行为,但我有一个特定组件,我想用自定义 non null
值替换 null
。
有什么通用的好方法可以实现吗?
我已经用 Mojarra 2.3.8 为 Primefaces (6.2) 日历试过这个:
<h:form id="myForm">
<p:calendar value="#{myBean.someDate}" pattern="MM/dd/yyyy"
converter="mySpecialDateConverter" locale="en" />
<p:commandButton value="send" process="@form" update="@form" />
<hr />
<h:outputText value="#{myBean.someDate}" />
</h:form>
我尝试使用一个转换器,当从 #{myBean.someDate}
收到我的自定义值时,在 getAsString()
中渲染组件 returns 一个 empty String
,或者吐出我的当提交null
或纯空时getAsObject()
中的自定义值:
import java.util.Date;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.DateTimeConverter;
import javax.faces.convert.FacesConverter;
@FacesConverter("mySpecialDateConverter")
public class MyConverter extends DateTimeConverter {
private static final Date PAST = new Date(0);
public MyConverter() {
setPattern("MM/dd/yyyy");
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (PAST.equals(value)) {
return "";
}
return super.getAsString(context, component, value);
}
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (null == value || "".equals(value.trim())) {
return PAST;
}
return super.getAsObject(context, component, value);
}
}
当 bean 属性 等于 PAST
时呈现空日历组件按预期工作。但是在没有输入的情况下提交日历会将 属性 设置为 null
因为 Primefaces CalendarRenderer
根本不会在提交空白值时参考 Converter
:
package org.primefaces.component.calendar;
public class CalendarRenderer extends InputRenderer {
// ...
public Object getConvertedValue(FacesContext context, UIComponent component, Object value) throws ConverterException {
Calendar calendar = (Calendar) component;
String submittedValue = (String) value;
SimpleDateFormat format = null;
if (isValueBlank(submittedValue)) {
return null;
}
//Delegate to user supplied converter if defined
try {
Converter converter = calendar.getConverter();
if (converter != null) {
return converter.getAsObject(context, calendar, submittedValue);
}
}
// ...
}
// ...
}
这部分没问题,正如 Converter.getAsObject()
上的 JavaDoc 所说:
/**
* @return <code>null</code> if the value to convert is <code>null</code>,
* otherwise the result of the conversion
*/
Primefaces 没有理由在空输入时解析转换器。如果我们设置 javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL = false
,恕我直言,情况会有所不同。然后我认为上述行为不正确,因为 ""
不是 null
.
为了完整起见,这是我的 bean myBean
:
import java.io.Serializable;
import java.util.Date;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
@Named
@ViewScoped
public class MyBean implements Serializable {
private static final long serialVersionUID = 1L;
private Date someDate;
public Date getSomeDate() {
return someDate;
}
public void setSomeDate(Date someDate) {
this.someDate = someDate;
}
}
我不想更改该 bean,因为在实际应用程序中,Calendars 的值绑定到持久实体 属性 值。我也不希望持久层完成这项工作。
非常背景:
我想阻止某些数据库 DATE
字段中的 null
值。例如,在期间的情况下,我希望开始默认为与应用程序上下文无关的某个遥远的过去日期,对于该期间的结束,我想要一个与应用程序上下文无关的遥远未来的日期,并且两者都不会打扰用户哪些日期他们是默认的。这些默认日期有助于过滤当前 Date
在该时间段内或之外的实体,同时假设用户没有输入实际上是在时间段 for ever
.
JSF 组件不会在空值或它们认为为空的任何值上调用转换器 - 这对于 JSF 中的默认组件也是如此。所以在这方面,我猜想 PrimeFaces 的行为符合预期,这是正确的结果。这里有两种立即想到的规避方法;
使用 OmniFaces
如 JSF converter with null value 中所述,OmniFaces o:param
将调用您的转换器而不考虑空值 - 您可以使用它向组件传递参数。在您的具体情况下,您应该能够执行与此类似的操作;
<h:form id="myForm">
<p:calendar value="#{myBean.someDate}" pattern="MM/dd/yyyy" locale="en" />
<p:commandButton value="send" process="@form" update="@form">
<o:param name="date" value="#{myBean.someDateConversion}"
converter="mySpecialDateConverter" />
</p:commandButton>
<hr />
<h:outputText value="#{myBean.someDate}" />
</h:form>
使用自定义渲染器
第二个选项是使用自定义渲染器,只需修改组件的行为以始终调用转换器,如此答案中所述 - JSF Custom Converter not called on null value。