jsf复合组件getConvertedValue过早激发

jsf复合组件getConvertedValue过早激发,jsf,children,composite-component,Jsf,Children,Composite Component,在我的应用程序中,我创建了一个compositeComponent,其中包含一组输入字段(例如,street、city、country)。该组件扩展了UIInput,因为我想返回由输入字段创建的完整位置对象。 问题是compositeComponent的getConvertedValue()在提交InputText之前被激发,因此这些值始终为空 我做错了什么 复合组件: <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http

在我的应用程序中,我创建了一个compositeComponent,其中包含一组输入字段(例如,street、city、country)。该组件扩展了
UIInput
,因为我想返回由输入字段创建的完整
位置
对象。 问题是compositeComponent的
getConvertedValue()
在提交InputText之前被激发,因此这些值始终为空

我做错了什么

复合组件:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:rich="http://richfaces.org/rich"
    xmlns:a4j="http://richfaces.org/a4j" xmlns:p="http://primefaces.org/ui"
    xmlns:composite="http://java.sun.com/jsf/composite">

<composite:interface componentType="locationInput">
    <composite:attribute name="value" />
</composite:interface>


<composite:implementation>
    <style>
.noPadding td {
    padding: 0px !important;
}
</style>
    <span id="#{cc.id}"> <p:panelGrid styleClass="noPadding" id="grd">
            <p:row>
                <p:column>
                    <p:outputLabel value="Straße/Nr." />
                </p:column>
                <p:column>
                    <p:inputText value="#{cc.street}" size="30" required="true" />
                    <p:inputText value="#{cc.houseNr}" size="4" required="true" />
                </p:column>
                <p:column style="width:20px" />
                <p:column>
                    <p:outputLabel value="PLZ" />
                </p:column>
                <p:column>
                    <p:inputText value="#{cc.zipCode}" size="30" required="true" />
                </p:column>
            </p:row>
            <p:row>
                <p:column>
                    <p:outputLabel value="Stadt" />
                </p:column>
                <p:column>
                    <p:inputText value="#{cc.city}" size="30" required="true" />
                </p:column>
                <p:column style="width:20px" />
                <p:column>
                    <p:outputLabel value="Land" />
                </p:column>
                <p:column>
                    <p:autoComplete forceSelection="true" dropdown="true"
                        required="true" cache="true" value="#{cc.country}"
                        completeMethod="#{countryBean.complete}" var="entry"
                        scrollHeight="200" itemValue="#{entry}" itemLabel="#{entry.name}"
                        converter="countryConverter" />
                </p:column>
            </p:row>
        </p:panelGrid>
    </span>
</composite:implementation>
</html>
import java.io.IOException;

import javax.faces.component.FacesComponent;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIInput;
import javax.faces.component.UINamingContainer;
import javax.faces.context.FacesContext;

@FacesComponent("locationInput")
public class LocationInput extends UIInput implements NamingContainer {

    @Override
    public String getFamily() {
        return UINamingContainer.COMPONENT_FAMILY;
    }

    @Override
    public void encodeBegin(FacesContext context) throws IOException {
        super.encodeBegin(context);
    }

    @Override
    public Object getSubmittedValue() {
        return this;
    }

    @Override
    protected Object getConvertedValue(FacesContext context, Object submittedValue) {
        System.out.println("THIS IS FIRED BEFORE THE COUNTRY/CITY/... gets submitted");
        return new Location(getStreet(), getCity(), getCountry());
    }

    public void setCountry(String country) {
        this.getStateHelper().put("countryValue", country);
    }

    public String getCountry() {
        return (String) this.getStateHelper().get("countryValue");
    }

    public void setCity(String city) {
        this.getStateHelper().put("cityValue", city);
    }

    public String getCity() {
        return (String) this.getStateHelper().get("cityValue");
    }

    public void setZipCode(String zipCode) {
        this.getStateHelper().put("zipCodeValue", zipCode);
    }

    public String getZipCode() {
        return (String) this.getStateHelper().get("zipCodeValue");
    }

    public void setHouseNr(String houseNr) {
        this.getStateHelper().put("houseNrValue", houseNr);
    }

    public String getHouseNr() {
        return (String) this.getStateHelper().get("houseNrValue");
    }

    public void setStreet(String street) {
        this.getStateHelper().put("streetValue", street);
    }

    public String getStreet() {
        return (String) this.getStateHelper().get("streetValue");
    }
}
getStreet()
getCity()
getCountry()
在更新模型值阶段之前不会更新,因此在流程验证阶段获取
null
值是正常的

另一种解决方案是在输入中使用
绑定
属性,如:

 <p:inputText binding="#{cc.street}" size="30" required="true" />
另请参见:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:rich="http://richfaces.org/rich"
    xmlns:a4j="http://richfaces.org/a4j" xmlns:p="http://primefaces.org/ui"
    xmlns:composite="http://java.sun.com/jsf/composite">

<composite:interface componentType="locationInput">
    <composite:attribute name="value" />
</composite:interface>


<composite:implementation>
    <style>
.noPadding td {
    padding: 0px !important;
}
</style>
    <span id="#{cc.id}"> <p:panelGrid styleClass="noPadding" id="grd">
            <p:row>
                <p:column>
                    <p:outputLabel value="Straße/Nr." />
                </p:column>
                <p:column>
                    <p:inputText value="#{cc.street}" size="30" required="true" />
                    <p:inputText value="#{cc.houseNr}" size="4" required="true" />
                </p:column>
                <p:column style="width:20px" />
                <p:column>
                    <p:outputLabel value="PLZ" />
                </p:column>
                <p:column>
                    <p:inputText value="#{cc.zipCode}" size="30" required="true" />
                </p:column>
            </p:row>
            <p:row>
                <p:column>
                    <p:outputLabel value="Stadt" />
                </p:column>
                <p:column>
                    <p:inputText value="#{cc.city}" size="30" required="true" />
                </p:column>
                <p:column style="width:20px" />
                <p:column>
                    <p:outputLabel value="Land" />
                </p:column>
                <p:column>
                    <p:autoComplete forceSelection="true" dropdown="true"
                        required="true" cache="true" value="#{cc.country}"
                        completeMethod="#{countryBean.complete}" var="entry"
                        scrollHeight="200" itemValue="#{entry}" itemLabel="#{entry.name}"
                        converter="countryConverter" />
                </p:column>
            </p:row>
        </p:panelGrid>
    </span>
</composite:implementation>
</html>
import java.io.IOException;

import javax.faces.component.FacesComponent;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIInput;
import javax.faces.component.UINamingContainer;
import javax.faces.context.FacesContext;

@FacesComponent("locationInput")
public class LocationInput extends UIInput implements NamingContainer {

    @Override
    public String getFamily() {
        return UINamingContainer.COMPONENT_FAMILY;
    }

    @Override
    public void encodeBegin(FacesContext context) throws IOException {
        super.encodeBegin(context);
    }

    @Override
    public Object getSubmittedValue() {
        return this;
    }

    @Override
    protected Object getConvertedValue(FacesContext context, Object submittedValue) {
        System.out.println("THIS IS FIRED BEFORE THE COUNTRY/CITY/... gets submitted");
        return new Location(getStreet(), getCity(), getCountry());
    }

    public void setCountry(String country) {
        this.getStateHelper().put("countryValue", country);
    }

    public String getCountry() {
        return (String) this.getStateHelper().get("countryValue");
    }

    public void setCity(String city) {
        this.getStateHelper().put("cityValue", city);
    }

    public String getCity() {
        return (String) this.getStateHelper().get("cityValue");
    }

    public void setZipCode(String zipCode) {
        this.getStateHelper().put("zipCodeValue", zipCode);
    }

    public String getZipCode() {
        return (String) this.getStateHelper().get("zipCodeValue");
    }

    public void setHouseNr(String houseNr) {
        this.getStateHelper().put("houseNrValue", houseNr);
    }

    public String getHouseNr() {
        return (String) this.getStateHelper().get("houseNrValue");
    }

    public void setStreet(String street) {
        this.getStateHelper().put("streetValue", street);
    }

    public String getStreet() {
        return (String) this.getStateHelper().get("streetValue");
    }
}

您已使用[processing]标记对此进行了标记。这是关于处理语言的问题吗?不,显然不是。我取下了标签@OP:在添加标签之前,请仔细阅读标签说明。感谢您提供的这些信息,我不知道这一点,因为我对jsf,尤其是复合组件非常陌生。