此解决方案基于 PF 6.0,我不记得BeanValidationMetadataExtractor
在以前的版本中是否可用。无论如何,创建一个 DIY 提取器是一项简单的任务。
我有一个类似的问题。在我的具体情况下:
- 应告知用户某个字段(读取
UIInput
)是必需的
- 我不想
required="true"
在 comp 上重复,因为它已经绑定到@NotNull
/ @NotBlank
property/field
- 在我的情况下,标签组件可能不存在(而且我不喜欢星号标签)
所以,这就是我所做的:
import java.util.Set;
import javax.el.ValueExpression;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.PreRenderComponentEvent;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
import javax.validation.constraints.NotNull;
import javax.validation.metadata.ConstraintDescriptor;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.NotEmpty;
import org.omnifaces.util.Faces;
import org.primefaces.context.RequestContext;
import org.primefaces.metadata.BeanValidationMetadataExtractor;
public class InputValidatorConstraintListener implements SystemEventListener
{
@Override
public boolean isListenerForSource(Object source)
{
return source instanceof UIInput;
}
@Override
public void processEvent(SystemEvent event) throws AbortProcessingException
{
if(event instanceof PreRenderComponentEvent)
{
UIInput component = (UIInput) event.getSource();
component.getPassThroughAttributes().computeIfAbsent("data-required", k ->
{
ValueExpression requiredExpression = component.getValueExpression("required");
if(requiredExpression != null || !component.isRequired())
{
FacesContext context = Faces.getContext();
ValueExpression valueExpression = component.getValueExpression("value");
RequestContext requestContext = RequestContext.getCurrentInstance();
try
{
Set<ConstraintDescriptor<?>> constraints = BeanValidationMetadataExtractor.extractAllConstraintDescriptors(context, requestContext, valueExpression);
if(constraints != null && !constraints.isEmpty())
{
return constraints.stream()
.map(ConstraintDescriptor::getAnnotation)
.anyMatch(x -> x instanceof NotNull || x instanceof NotBlank || x instanceof NotEmpty);
}
}
catch(Exception e)
{
return false;
}
}
return false;
});
}
}
}
并在 faces-config.xml 中声明:
<?xml version="1.0" encoding="utf-8"?>
<faces-config version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<application>
<system-event-listener>
<system-event-listener-class>it.shape.core.jsf.listener.InputValidatorConstraintListener</system-event-listener-class>
<system-event-class>javax.faces.event.PreRenderComponentEvent</system-event-class>
</system-event-listener>
</application>
</faces-config>
使用这个 listener s 会使用passthrough 属性UIInput
进行渲染:data-required
<input
id="form:editPanelMain:j_idt253"
name="form:editPanelMain:j_idt253"
type="text"
value="Rack Assemply"
size="80"
data-required="true" <============================ NOTE THIS!!
data-widget="widget_form_editPanelMain_j_idt253"
class="ui-inputfield ui-inputtext ui-widget ui-state-default ui-corner-all"
role="textbox"
aria-disabled="false"
aria-readonly="false">
现在,我使用 css 规则突出显示这些字段:
input[data-required='true'],
.ui-inputfield[data-required='true'],
*[data-required='true'] .ui-inputfield {
box-shadow: inset 0px 2px 2px #bf8f8f;
}
您可以调整此侦听器以根据需要设置组件或使用适合您特定需求的其他方法。
另一种方法可能是:
- 听
UILabel
s 而不是UIInput
s
- 获取
UIInput
与标签的for
/ forValue
ValueExpression 关联的
- 检查
UIInput
验证约束
- 最终调用
UIInput.setRequired(true)
性能影响可以忽略不计,因为我已经测试了大约 3000 个组件的复杂页面。