Богатая подсказка для SelectItem - PullRequest
1 голос
/ 22 апреля 2010

Как прикрепить rich:tooltip к списку, сгенерированному f:selectItems при использовании переменной для атрибута for внутри rich:tooltip.

Этот код работает нормально (значение #{prefix} равно theprefixvalue

<ui:composition>
<a4j:form id="#{prefix}_form">
<h:selectOneRadio style="text-align:left" id="#{prefix}_rating">
<f:selectItems value="#{test.options}"></f:selectItems>
</h:selectOneRadio>&nbsp; 
<rich:toolTip for="theprefixvalue_form\:theprefixvalue_rating\:0">a</rich:toolTip>      
</a4j:form>
</ui:composition>

Но этот код не:

<ui:composition>
<h:outputText value="#{prefix}" />
<a4j:form id="#{prefix}_form">
<h:selectOneRadio style="text-align:left" id="#{prefix}_rating">
<f:selectItems value="#{test.options}"></f:selectItems>
</h:selectOneRadio>&nbsp; 
<rich:toolTip for="#{prefix}_form\:#{prefix}_rating\:0">a</rich:toolTip>        
</a4j:form>
</ui:composition>

Выдает следующее исключение:

Caused by: java.lang.IllegalArgumentException: theprefixvalue_rating
    at javax.faces.component.UIComponentBase.findComponent(UIComponentBase.java:612)
    at org.ajax4jsf.renderkit.RendererUtils.findComponentFor(RendererUtils.java:1037)
    at org.richfaces.renderkit.html.ToolTipRenderer.getTargetId(ToolTipRenderer.java:234)
    at org.richfaces.renderkit.html.ToolTipRenderer.constructJSVariable(ToolTipRenderer.java:251)
...

TestBean имеет сессионную область, и это код для getOptions ();

public List<SelectItem> getOptions(){
    List<SelectItem> options = new ArrayList<SelectItem>();
    options.add(new SelectItem("a","a"));
    options.add(new SelectItem("b","b"));
    options.add(new SelectItem("c","c"));
    return options;

}

Есть идеи? Цель состоит в том, чтобы иметь подсказку, когда указатель мыши находится над различными параметрами. Заранее спасибо.

Редактировать: Очевидно, HtmlSelectOneRadio не реализует NamingContainer, поэтому происходит сбой в UIComponentBase строка 611: (result является экземпляром HtmlSelectOneRadio, length>0 и segments[1] = "theprefixvalue_rating")

        if (result != null && (!(result instanceof NamingContainer)) && length > 0) {
            throw new IllegalArgumentException(segments[i]);

Я пытаюсь использовать свой собственный NamedHtmlSelectOneRadio, который расширяет HtmlSelectOneRadio и реализует NamingContainer, но я все еще гадаю, как ввести его с помощью facelets. Есть идеи?

1 Ответ

3 голосов
/ 23 апреля 2010

Наконец мне удалось это решить.

Я создал свой собственный компонент с именем NamedHtmlSelectOneRadio, который является просто оболочкой HtmlSelectOneRadio, но реализует NamingContainer. Я не знаю, будет ли это иметь дальнейшие последствия для остальной части кода JSF, но мой тестовый сценарий работает нормально. В любом случае, я обновлю этот ответ, если найду какое-то странное поведение, а также опубликую в реализации JSF в Mojarra информацию о том, почему HtmlSelectOneRadi o не реализует NamingContainer из коробки.

Вот шаги для создания вашего собственного компонента с Facelets.

1 Оберните класс:

import javax.faces.component.NamingContainer; import javax.faces.component.html.HtmlSelectOneRadio;

public class NamedHtmlSelectOneRadio extends HtmlSelectOneRadio implements NamingContainer {

    public NamedHtmlSelectOneRadio(){
        super();
    }

}

2 Оберните класс Tag и установите вышеуказанный класс в качестве компонента. Тип:

import com.sun.faces.taglib.html_basic.SelectOneRadioTag;

public class NamedHtmlSelectOneRadioTag extends SelectOneRadioTag {

    public NamedHtmlSelectOneRadioTag(){
        super();
    }
    @Override
    public String getComponentType() {
        return "javax.faces.NamedHtmlSelectOneRadio";
    }

}

3 Добавьте компонент в faces-config.xml конфигурацию:

<component>
<component-type> com.eyeprevent.util.NamedHtmlSelectOneRadio </component-type>
<component-class> com.eyeprevent.util.NamedHtmlSelectOneRadio </component-class>
</component>

4 Добавьте тег в ваш taglib (мой файл functions.taglib.xml). Подробнее о создании собственного taglib здесь

<tag>
<tag-name>namedSelectOneRadio</tag-name>
<component>
<component-type>com.eyeprevent.util.NamedHtmlSelectOneRadio</component-type>
</component>
</tag>`

5 Включите новый taglib на свою страницу .xhtml (или .jsf) и замените h:selectOneRadio своим собственным (у меня fnc:namedSelectOneRadio)

xmlns:fnc="http://eyeprevent.com/fnc"
...

<fnc:namedSelectOneRadio id="#{prefix}_rating">
<f:selectItems value="#{test.options}"></f:selectItems>
</fnc:namedSelectOneRadio>
<rich:toolTip for="#{prefix}_form\:#{prefix}_rating:0">a</rich:toolTip>

И это все!

...