JSF Композитный компонентсодержит неизвестный идентификатор - не может найти его в контексте компонента - PullRequest
8 голосов
/ 25 марта 2012

Я пытаюсь обновить родительский компонент из события составного компонента, используя f:ajax.

Композитный компонент находится здесь:

<cc:interface>
    <cc:attribute name="update" />
    <cc:attribute name="customid" required="true"/>
    <cc:attribute name="val" required="true"/>
    <cc:attribute name="selectedvalue" required="true"/>
</cc:interface>
<cc:implementation>
    <h:panelGrid columns="2" style="font-size: 10px" >
        <p:selectOneMenu id="#{cc.attrs.customid} value="#{cc.attrs.selectedvalue}">
            <f:selectItems value="#{cc.attrs.val}"/>
            <f:ajax event="change" render="#{cc.attrs.update" />
        </p:selectOneMenu>
        <p:commandButton type="button" icon="ui-icon-plus" onclick="dlg.show();" />
    </h:panelGrid>
</cc:implementation>

Теперь при использовании этого компонента выполните следующие действия:

<h:form>
    <ez:combo customid="make" val="#{vehicleBean.makes}" selectedvalue="#vehicleBean.vehicle.make}" update="model"  />
    <p:selectOneMenu id="model" value="#{vehicleBean.vehicle.model}">
        <f:selectItems value="#{vehicleBean.models}" />
    </p:selectOneMenu>
</h:form>

Я получаю следующую ошибку:

содержит неизвестный идентификатор 'модель' - не может найти его в контексте компонента make

Ответы [ 2 ]

15 голосов
/ 25 марта 2012

Поскольку компонент для обновления находится за пределами cc, вы должны обращаться к нему по-другому. Сначала дайте вашей форме идентификатор:

<h:form id="myform">

Затем адресуйте целевой компонент из вашего cc следующим образом:

render=":myform:model"

Обратите внимание на двоеточие в конце, которое позволяет JSF искать атрибут в корне документа.

4 голосов
/ 04 февраля 2013

У меня была такая же проблема некоторое время назад, просто для информации я проверил источники реализации jsf mojara; вот как это работает: Класс ajaxBehaviorRendered при обнаружении элемента f: ajax для рендеринга анализирует содержимое атрибута render через его метод getResolvedId:


private static String getResolvedId(UIComponent component, String id) {

        UIComponent resolvedComponent = component.findComponent(id);
        if (resolvedComponent == null) {
...

Точка - это метод findComponent: для этого нужна базовая база компонентов как начальная точка для поиска в дереве компонентов. Если идентификатор начинается с символа «:», компонентной базой является viewRoot.



    UIComponent base = this;
     if (expr.charAt(0) == sepChar) {
        // Absolute searches start at the root of the tree
        while (base.getParent() != null) {
            base = base.getParent();
         }
        expr = expr.substring(1);
    }

В противном случае базовый компонент является ближайшим родителем текущего компонента типа NamingContainer (т. Е. Вашего составного компонента, в котором вы определяете свой компонент AJAX).



    //Treat remainder of the expression as relative
    else if (!(base instanceof NamingContainer)) {
        // Relative expressions start at the closest NamingContainer or root
        while (base.getParent() != null) {
            if (base instanceof NamingContainer) {
                break;
            }
            base = base.getParent();
        }
    }

Затем в обоих случаях он начинает поиск компонента с заданным идентификатором с этого запуска.

Это поведение, указанное в jsf.

С моей точки зрения, если вам нужно сослаться на компонент вне композита, вы должны определить полное имя, используя префикс «:», за которым следует атрибут «cc.clientId».

...