Почему commandLink внутри фасета составного компонента отображает ошибку?

Когда я создаю составной компонент с фасетом в нем и помещаю ссылку на команду в этот фасет, я получаю сообщение об ошибке: This link is disabled as it is not nested within a JSF form.

CommandButton ведет себя не так, так что я склоняюсь к тому, что это баг.

index.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>
<!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://xmlns.jcp.org/jsf/html"
      xmlns:mycomp="http://xmlns.jcp.org/jsf/composite/mycomp"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head>
    </h:head>
    <h:body>
        <mycomp:component>
            <f:facet name="someFacet">
                <h:commandLink value="this link should work, but does not (within form, within facet)"/><br/>
                <h:commandButton value="this button works as expected (within form, within facet)"/><br/>
            </f:facet>
        </mycomp:component>
    </h:body>
</html>

/resources/mycomp/component.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>
<ui:component
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:cc="http://xmlns.jcp.org/jsf/composite"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:a="http://xmlns.jcp.org/jsf/passthrough"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
    >
    <cc:interface>
        <cc:facet name="someFacet" required="true"/>
    </cc:interface>
    <cc:implementation>
        <h:commandLink value="this link should not work (not in a form)"/><br/>
        <h:form>
            <h:commandLink value="this link works as expected (within form, but not in facet)"/><br/>
            <cc:renderFacet name="someFacet"/>
        </h:form>
    </cc:implementation>
</ui:component>

Вот что делает мой браузер:

введите описание изображения здесь

Любые идеи относительно того, что я могу делать неправильно, или это действительно ошибка в Mojarra 2.2.7? (который поставлялся в комплекте с NetBeans 8.0.2)


person Leo Mekenkamp    schedule 13.08.2015    source источник
comment
Тот же вывод отображается для Mojarra 2.1.6 (за исключением оранжевых маркеров).   -  person DavidS    schedule 13.08.2015
comment
Интересно, возможно, вы просто неправильно используете фасеты (ref и ref). Я никогда не был полностью уверен в фасетах, но они, похоже, являются способом предоставления входных данных для родительского компонента. form не принимает фасет с именем someFacet, поэтому поведение не определено. Я не уверен, хотя, поэтому я не буду публиковать ответ.   -  person DavidS    schedule 13.08.2015
comment
Это действительно ошибка. Вам лучше просто сообщить об этом. Однако наличие формы внутри композита, в свою очередь, является дизайнерским запахом. Не слишком ли много делает ваш композит? См. также stackoverflow.com/questions/6822000/   -  person BalusC    schedule 14.08.2015
comment
@DavidS Не h:form, а этот компонент принимает фасет под названием someFacet: предположительно дополнительный контент для формы.   -  person user207421    schedule 14.08.2015
comment
Да, возможно, я слишком стараюсь здесь; Я пытался создать композит, который использует два набора компонентов commandLink для построения структуры меню. HTML-код, который необходимо отобразить, уже определен, так что обойти два набора невозможно.   -  person Leo Mekenkamp    schedule 16.08.2015
comment
Это все еще проблема в Mojarra 2.3.3.   -  person Vsevolod Golovanov    schedule 08.12.2020


Ответы (2)


старый поток, но я думаю, что текущее поведение является ошибкой, потому что следующее работает, и поэтому оно должно работать в составном компоненте:

component.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>
<ui:component
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:cc="http://xmlns.jcp.org/jsf/composite"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:a="http://xmlns.jcp.org/jsf/passthrough"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
>
<cc:interface>
    <cc:facet name="someFacet" required="true"/>
</cc:interface>
<cc:implementation>
    <h:commandLink value="this link should not work (not in a form)"/><br/>
        <h:commandLink value="this link works as expected (within form, but not in facet)"/><br/>
        <cc:renderFacet name="someFacet"/>
</cc:implementation>
</ui:component>

Используя его (index.xhtml):

<?xml version='1.0' encoding='UTF-8' ?>
<!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://xmlns.jcp.org/jsf/html"
      xmlns:mycomp="http://xmlns.jcp.org/jsf/composite/mycomp"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head>
    </h:head>
    <h:body>
     <h:form>
        <mycomp:component>
            <f:facet name="someFacet">
                <h:commandLink value="this link should work, but does not (within form, within facet)"/><br/>
                <h:commandButton value="this button works as expected (within form, within facet)"/><br/>
            </f:facet>
        </mycomp:component>
      </h:form>
    </h:body>
</html>

Также сгенерированный вывод HTML в обоих случаях генерирует кнопку в нужном месте в дереве компонентов (под формой). Но clientId, сгенерированный для кнопки, отличается в обоих случаях:

  • Сообщение первой темы --> clientId без идентификатора формы
  • Мой пост --> clientId включает идентификатор формы

На мой взгляд, это похоже на ошибку, но, возможно, кто-то сможет убедить меня, что это не так ;D

Использование Mojarra 2.2.13 (Primefaces 6.x).

person Daniel K.    schedule 19.12.2017

Я делаю то же самое, за исключением того, что я вставляю p: commandButton PrimeFaces через фасет - кнопка работает, единственная проблема - предупреждения, поэтому я предлагаю решение для них.

Добавьте тип компонента:

<cc:interface componentType="myComponent">

И соответствующий класс Java:

import javax.faces.component.FacesComponent;
import javax.faces.component.UINamingContainer;
import javax.faces.component.UIOutput;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;

@FacesComponent
public class MyComponent extends UIOutput /* or UINamingContainer - depends on what you need */ {

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

    @Override
    public boolean visitTree(VisitContext context, VisitCallback callback) {
        // skip the form checks; we know the form is guaranteed by the component anyway
        String callbackName = callback.getClass().getName();
        if (callbackName.contains("ValidateFormNestingCallback") || callbackName.contains("FormOmittedChecker")) {
            return false;
        }

        return super.visitTree(context, callback);
    }

}

Протестировано с моджаррой 2.3.3.

person Vsevolod Golovanov    schedule 08.12.2020