本文介绍了为Primefaces添加自定义属性(HTML5)支持(3.4)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试在我的JSF / Primefaces Web应用程序中实现简单的html5属性autofocus时,我被提醒的事实是组件没有将所有未知属性传递给最终标记。我可以理解这一点的原因,因为组件可能是html标记的复杂组合,如果属性尚未由组件定义,则不清楚放置属性的位置。

In trying to implement the simple html5 attribute 'autofocus' in my JSF/Primefaces web-application, I was alerted to the fact that the components do not pass all unknown attributes on to the final markup. I can understand reasonings for this, as components can be complex combinations of html markup and it would not be clear where to place the attributes if they are not already well-defined by the component.

但对我来说最好的解决方案是支持自动对焦(以及我可能希望在我的应用程序中支持的任何其他可能类型的属性,其中primefaces尚未定义)。

But the best solution for me is to have support for autofocus (and any other possible types of attributes I may want to support in my application that primefaces has not defined).

我见过,但这似乎适用于基本的JSF组件,不适用于PrimeFaces组件。

I have seen Adding custom attribute (HTML5) support to JSF 2.0 UIInput component, but that seems to apply for the basic JSF components and does not work for PrimeFaces components.

我如何扩展Primefaces的组件/渲染以支持这个?

How do I extend the component/rendering of Primefaces to support this?

推荐答案

而不是为每个单个组件自定义渲染器,你可以也只是创建一个,其中提供了自定义其中方法被覆盖以检查元素名称和/或组件实例然后写入相应的其他属性。

Instead of homegrowing a custom renderer for every single individual component, you could also just create a single RenderKit wherein you provide a custom ResponseWriter wherein the startElement() method is overriden to check the element name and/or component instance and then write additional attributes accordingly.

以下是HTML5渲染工具包的启动示例:

Here's a kickoff example of the HTML5 render kit:

public class Html5RenderKit extends RenderKitWrapper {

    private RenderKit wrapped;

    public Html5RenderKit(RenderKit wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public ResponseWriter createResponseWriter(Writer writer, String contentTypeList, String characterEncoding) {
        return new Html5ResponseWriter(super.createResponseWriter(writer, contentTypeList, characterEncoding));
    }

    @Override
    public RenderKit getWrapped() {
        return wrapped;
    }

}

HTML5响应编写者:

The HTML5 response writer:

public class Html5ResponseWriter extends ResponseWriterWrapper {

    private static final String[] HTML5_INPUT_ATTRIBUTES = { "autofocus" };

    private ResponseWriter wrapped;

    public Html5ResponseWriter(ResponseWriter wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public ResponseWriter cloneWithWriter(Writer writer) {
        return new Html5ResponseWriter(super.cloneWithWriter(writer));
    }

    @Override
    public void startElement(String name, UIComponent component) throws IOException {
        super.startElement(name, component);

        if ("input".equals(name)) {
            for (String attributeName : HTML5_INPUT_ATTRIBUTES) {
                String attributeValue = component.getAttributes().get(attributeName);

                if (attributeValue != null) {
                    super.writeAttribute(attributeName, attributeValue, null);
                }
            }
        }
    }

    @Override
    public ResponseWriter getWrapped() {
        return wrapped;
    }

}

要让它运行,请创建这个HTML5渲染工具包工厂:

To get it to run, create this HTML5 render kit factory:

public class Html5RenderKitFactory extends RenderKitFactory {

    private RenderKitFactory wrapped;

    public Html5RenderKitFactory(RenderKitFactory wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public void addRenderKit(String renderKitId, RenderKit renderKit) {
        wrapped.addRenderKit(renderKitId, renderKit);
    }

    @Override
    public RenderKit getRenderKit(FacesContext context, String renderKitId) {
        RenderKit renderKit = wrapped.getRenderKit(context, renderKitId);
        return (HTML_BASIC_RENDER_KIT.equals(renderKitId)) ? new Html5RenderKit(renderKit) : renderKit;
    }

    @Override
    public Iterator<String> getRenderKitIds() {
        return wrapped.getRenderKitIds();
    }

}

并在 faces-config.xml

<factory>
    <render-kit-factory>com.example.Html5RenderKitFactory</render-kit-factory>
</factory>

JSF实用程序库也有这样的渲染工具包,()理论上应该也可以在PrimeFaces组件上正常工作。然而,这个问题迫使我再次重新审视,我很尴尬地看到 ResponseWriter#startElement()组件参数c $ c> null in < p:inputText> (参见,它应该是 writer.startElement(input,inputText)代替)。我不确定这是故意的还是对PrimeFaces渲染器设计的疏忽,但你可以使用 UIComponent#getCurrentComponent()代替它。

The JSF utility library OmniFaces has also such a render kit, the Html5RenderKit (source code here) which should theoretically also work fine on PrimeFaces components. However, this question forced me to take a second look again and I was embarrassed to see that the component argument in ResponseWriter#startElement() is null in <p:inputText> (see line 74 of InputTextRenderer, it should have been writer.startElement("input", inputText) instead). I'm not sure if this is intentional or an oversight in the design of the PrimeFaces renderer or not, but you could use UIComponent#getCurrentComponent() instead to get it.

更新:这在OmniFaces 1.5中得到修复。

Update: this is fixed in OmniFaces 1.5.

值得注意的是,即将到来的JSF 2.2将支持通过新的 passthrough 命名空间或< f:passThroughAttribute> 标记。另请参见。

Noted should be that the upcoming JSF 2.2 will support defining custom attributes in the view via the new passthrough namespace or the <f:passThroughAttribute> tag. See also What's new in JSF 2.2? - HTML5 Pass-through attributes.

因此,所以:

<html ... xmlns:p="http://java.sun.com/jsf/passthrough">
...
<h:inputText ... p:autofocus="true" />

(您可能想要使用 a 而不是 p 作为名称空间前缀,以避免与PrimeFaces的默认名称空间冲突)

(you may want to use a instead of p as namespace prefix to avoid clash with PrimeFaces' default namespace)

或:

<h:inputText ...>
    <f:passThroughAttribute name="autofocus" value="true" />
</h:inputText>

这篇关于为Primefaces添加自定义属性(HTML5)支持(3.4)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-31 00:05