我有一个“复合组件”,用于选择一天和一个月(comp:daymonth):

<ui:composition ... >
    <cc:interface>
        <cc:attribute name="value" type="model.DayMonth" required="true" />    
        <cc:editableValueHolder name="forMonth" targets="selected_month" />
            ...
</cc:interface>            

<cc:implementation>
    <p:selectOneMenu id="selected_month" value="#{cc.attrs.value.monthAsString}">
        <f:selectItems value="#{cc.attrs.value.months}"/>
    </p:selectOneMenu>
...
</cc:implementation>

</ui:composition>

使用页面看起来像:

<h:form id="form">
     ...
        <comp:daymonth id="von" value="#{controller.von}">
          </comp:daymonth>
        <comp:daymonth id="bis"    value="#{controller.bis}">
            <f:validator binding="#{vonBisValidator}" for="forMonth"/>
        </comp:daymonth>
    ...
</h:form>

我想验证“von”的月份为“bis”(例如“bis”.selected_month大于“von”.selected_month) .

验证器看起来像:

@Named("vonBisValidator")
@ApplicationScoped
public class vonBisValidator implements Validator, Serializable {
    @Override
    public void validate(final FacesContext context, final UIComponent component, final Object value) throws ValidatorException {

    // Just to show what ist going on, the real implementation would check the values against each other, sets invalid and throws exception etc.    
    try {
        final UIViewRoot viewRoot = context.getViewRoot();

        final SelectOneMenu gueltigVon = (SelectOneMenu) viewRoot.findComponent("form:von:selected_month");
        final SelectOneMenu gueltigBis = (SelectOneMenu) viewRoot.findComponent("form:bis:selected_month");

        final Object vonValue = gueltigVon.getValue();
        final Object bisValue = gueltigBis.getValue();

        final Object bisValueS = gueltigBis.getSubmittedValue();
        final Object vonValueS = gueltigVon.getSubmittedValue();

        System.out.println("vonValue : " + vonValue + "\t bisValue :" + bisValue);
        System.out.println("vonValueS: " + vonValueS + "\t bisValueS:" + bisValueS);

    } catch (final Exception ex) {
        System.out.println(ex);
    }}

在屏幕上显示“von:Märzbis:Oktober”,正如数据库阅读所预期的那样 . 当我选择另一个“bis”时,例如 . Januar,System.out是:

vonValue : Oktober     bisValue :Oktober
vonValueS: null     bisValueS:Januar

Why ist vonValue of von-Component Oktober? Should it not be März?

之后我选择另一个“bis”,例如 . Februar,System.out是:

vonValue : Januar bisValue :Januar
vonValueS: null     bisValueS:Februar

Why ist vonValue of von-Component Januar?

调试器结果:

  • gueltigVon还有另一个java-id然后是gueltigBis . 找到了正确的组件 .

  • von和bis的ComponentStateHelper-id是不同的 .

  • 用于EL检索的component.getFacesContext() . getELContext()始终相同 .

  • 对于gueltigVon.getValue();:至于"von"提交的值并没有改变,localValue没有设置和的getValue(..)回落到super.gerValue(..)(javax.faces.component.ComponentStateHelper ) . 在那里,因为get(key)返回null,所以EL使用/从component.getFacesContext() . getELContext()读取值 . 这始终是相同的,因此搜索的值表达式"#"会产生请求的相同Object(然后是相同的值) .

ComponentStateHelper:

public Object eval(Serializable key, Object defaultValue) {
       Object retVal = get(key);
        if (retVal == null) {
            ValueExpression ve = component.getValueExpression(key.toString());
            if (ve != null) {
                retVal = ve.getValue(component.getFacesContext().getELContext());
            }
        }
        return ((retVal != null) ? retVal : defaultValue);
    }

为什么component.getFacesContext() . getELContext()不成立,ValueExpression.getValue(..)区分“composit component” - 组件值?

如何将一个“composit组件” - 组件值(例如selected_month)的值放入“composit组件” - 组件验证器中,以便对两个“composit组件”组件进行交叉字段验证?

或者,我的错误是什么?

Wilfdfly 10.1.0 PrimeFaces 6.1