1

ビジネス検証のために古い/新しい価値を捉えようとしています。そのためには、ValueChangeListener が適切な選択のように思えました。h:selectOneMenu では問題なく機能しましたが、バッキング コンポーネントを含む自家製の複合コンポーネントで使用すると呼び出されません。私が間違っていることは何か分かりますか?

追加することの 1 つは、state.xhtml から componentType 属性を削除すると、valueChangeListener が期待どおりに機能することです...

コンポーネント:

<!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:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"  
    xmlns:composite="http://java.sun.com/jsf/composite">

    <composite:interface displayName="state" componentType="com.company.dept.system.ui.address.State" shortDescription="State Information Display/Input Component">
        <composite:attribute name="value" type="java.lang.String" required="true" shortDescription="The value of the component" />      
        <composite:editableValueHolder name="state" />              
    </composite:interface>

    <composite:implementation>
    <div id="#{cc.clientId}">

            <h:selectOneMenu id="state" value="#{cc.attrs.value}">
                <f:selectItem itemLabel="(select)" noSelectionOption="true"/>
                <f:selectItems var="item" itemLabel="#{item.displayValue}" value="#{cc.states}" />
            </h:selectOneMenu>      

    </div>

    </composite:implementation>
</html>

バッキング コンポーネント

@FacesComponent("com.company.dept.system.ui.address.State")
public class State extends UIInput implements NamingContainer {

    private List<com.company.dept.policy.enums.State> states;

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

    /**
     * Prepare the list of states to display
     */
    public List<com.company.dept.policy.enums.State> getStates(){

        if (states != null) {
            return states;
        }

        states = new ArrayList<com.company.dept.policy.enums.State>();              
        for (com.company.dept.policy.enums.State st : com.company.dept.policy.enums.State.values()) {
            if(!st.equals(com.company.dept.policy.enums.State.NWNORWAY) && !st.equals(com.company.dept.policy.enums.State.UNKNOWN) &&  !st.equals(com.company.dept.policy.enums.State.TTTRUST_TERRITORY_AND_GUAM)) {            
                states.add(st);
            }
        }
        Collections.sort(states,new StateNameComparator());

        return states;
    }

}

値変更リスナー

public class ClientValueChangeListener implements ValueChangeListener {

    @Override
    public void processValueChange(ValueChangeEvent event)
            throws AbortProcessingException {
        System.out.println("*****************************");
        System.out.println("VALUE CHANGE LISTENER. OLD=" + event.getOldValue() + " - NEW=" + event.getNewValue());
        System.out.println("*****************************");
         }
}

消費ページ:

<h:form>
    <address:state value="#{testPage.state}">
        <f:valueChangeListener type="com.company.dept.system.ui.clientinformation.ClientValueChangeListener" for="state"/>
    </address:state>
    <h:commandButton id="submitButton" value="Test" action="#{testPage.act}"/>          
</h:form>
4

1 に答える 1

2

これは、バッキング コンポーネントが から拡張されているためUIInputです。値変更リスナーは、複合実装の子ではなく、バッキング コンポーネント自体に適用されます。

具体的な機能要件は明確ではありませんが、これまでに提供された情報に基づいて、安全に置き換えることができますextends UIInput implements NamingContainer(そしてオーバーライドextends UINamingContainerを取り除くことができます)。getFamily()

バッキング コンポーネントを から拡張することを本当に意図している場合はUIInput、送信された値、ローカル値、およびバッキング コンポーネントの値をすべて子ドロップダウン コンポーネントに委譲する必要がありますが、これは設計を技術的にほとんどまたはまったく意味をなさないものにします。

于 2013-06-18T15:38:27.120 に答える