Как я могу привязать UIComponent к тегу программно - PullRequest
0 голосов
/ 30 апреля 2019

Я пытаюсь создать повторно используемый компонент, который условно отображает соответствующий компонент ввода jsf на основе некоторых критериев. Я хочу отобразить тег h: inputText, если поле не содержит списка допустимых значений, или тег h: selectOneMenu, если указаны некоторые допустимые значения.

Я попытался установить привязку к переменной c: set и использовать переменную в нескольких тегах.

Я также пытался использовать обычный атрибут «value» вместо атрибута «binding».

@FacesComponent("extendedInput")
public class ExtendedInput extends UIInput implements NamingContainer {

    // Fields -------------------------------------------------------------------------------------

    private UIInput choice;

    // Actions ------------------------------------------------------------------------------------

    public ExtendedInput() {

    }

    @Override
    public void decode(FacesContext context) {
        super.decode(context);
    }
    /**
     * Returns the component family of {@link UINamingContainer}.
     * (that's just required by composite component)
     */
    @Override
    public String getFamily() {
        return UINamingContainer.COMPONENT_FAMILY;
    }

    /**
     * Set the selected and available values of the day, month and year fields based on the model.
     */
    @Override
    public void encodeBegin(FacesContext context) throws IOException {
        setDisplayInputText(true);
        setDisplaySelectOne(false);
        //get map from session scoped bean.
        Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
        PageOne page = (PageOne) viewMap.get("pageOne");
        String attributeName = (String) getAttributes().get("fieldName");

        AttributeMap attr = page.getFieldMap().get(attributeName);
        String allowedValues = attr.getAllowedValues();
        Map<String, String > selectOptions = new HashMap<String,String>();
        if (allowedValues != null && !allowedValues.isEmpty()) {
            setDisplayInputText(false);
            setDisplaySelectOne(true);
            String[] keyValString = allowedValues.split(";");
            for (String valString : keyValString) {
                String[] opt = valString.split("=");
                selectOptions.put(opt[0], opt[1]);
            }
        }
        setChoices(selectOptions);
        String opt = getValue().toString();
        choice.setValue(opt);
        super.encodeBegin(context);
    }
  //... getter / setters
}

Моя проблема в том, что я не могу использовать одну и ту же привязку для обоих компонентов, указанных ниже, даже если не обе они отображаются одновременно.

<ui:component
    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:cc="http://java.sun.com/jsf/composite"
    xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
    <cc:interface componentType="extendedInput">
        <cc:attribute name="value" type="java.lang.Object"
            shortDescription="value for bean property" />
        <cc:attribute name="fieldName" type="java.lang.String" required="true"
                      shortDescription="name of the attribute we are working with" />
    </cc:interface>
    <cc:implementation>
        <span id="#{cc.clientId}" style="white-space:nowrap">
            <h:selectOneMenu id="day" rendered="#{cc.displaySelectOne}" binding="#{cc.choice}">
                <f:selectItem itemLabel="Select One" itemValue="x" />
                <f:selectItems value="#{cc.choices.entrySet()}" var="opt"
                               itemLabel="#{opt.value}" itemValue="#{opt.key}" />
            </h:selectOneMenu>
            <h:inputText id="normalInput" rendered="#{cc.displayInputText}"  binding="#{cc.choice}"/>
        </span>
    </cc:implementation>
</ui:component>
...