Override ui: insert and ui: include-Handler

There are many other topics on how to override an existing render in JSF. They all lead to one entry in faces-config. You "need" only component-family

, renderer-type

, render-kit-id

and your implementation inrenderer-class

I understand and can reproduce all of these examples, but in my particular case, I would like to override the behavior <ui:include>

and <ui:insert>

. Unfortunately, I cannot find out what values ​​I need to include in the attributes mentioned above, because the file is ui:taglib.xml

not as verbose as the other tags.

Do you have any idea how to override them?

Edit: BalusC mentioned another section , it uses custom tags like <my:include>

or <my:insert>

, but that I don't want to use. If I did, I had to refactor all of my existing code and my future code won't work without using my custom taglib.

I would like to hook into the render <ui:include>

and <ui:insert>

so that I can reuse the plugin I am about to develop without modifying any existing code.

+3


source to share


1 answer


... without changing any existing code

You can not. At least without being closely related to a specific implementation (Mojarra or MyFaces). An alternative would be to bite the bullet and replace all <ui:include>

, and <ui:define>

on <my:include>

and <my:define>

. Faces are not yet fully abstracted / standardized in the JSF spec. There's only the Facelet factory cache , but not the Facelet factory context, otherwise it would be easy. As a rule of thumb, forget about customizing your tags in an <ui:xxx>

abstract way. You will need to hack the implementation.

Considering you are using Mojarra 2.1.19, you need to copypaste it com.sun.faces.facelets.impl.DefaultFaceletContext

into your web application project while maintaining it com.sun.faces.facelets.impl

. Classes in WAR have higher priority on loading than in WAR /WEB-INF/lib

and server /lib

. So this one in your WAR will be used instead.

Given that you would like to achieve the same as in Customize ui: enable rendering to add prefix / postfix on <ui:include>

and <ui:define>

:

Example, suppose an empty .xhtml file:

Input

<ui:include src="file.xhtml" />

      

Output

<!-- START file.xhtml -->
<!-- END file.xhtml -->

      



Here's how you can achieve this by editing the: copypasted class:

  • Add a helper method to the class that creates the comment component (which is just a simple text output component).

    private static UIComponent createComment(String comment) {
        UIOutput text = new UIOutput();
        text.setValue("\n<!-- " + comment + " -->\n");
        return text;
    }
    
          

  • Extend the oneliner method includeFacelet(UIComponent, String)

    on line 199 as shown below:

    parent.getChildren().add(createComment("START INCLUDE " + relativePath));
    facelet.include(this, parent, relativePath);
    parent.getChildren().add(createComment("END INCLUDE " + relativePath));
    
          

  • Expand includeDefinition(UIComponent, String)

    around line 366 with client.apply(this, parent, name)

    as shown below:

    int start = parent.getChildCount();
    found = client.apply(this, parent, name);
    
    if (found) {
        parent.getChildren().add(start, createComment("START DEFINE " + name));
        parent.getChildren().add(createComment("END DEFINE " + name));
    }
    
          

During testing, however, I found a caveat. I have an HTML template <title>

as shown below:

<h:head>
    <title><ui:insert name="title">#{view.viewId}</ui:insert></title>
</h:head>

      

This way, the comments also end up inside the element <title>

. Unfortunately, comments in the HTML header are not valid syntax (only PCDATA

allowed) and they are interpreted literally and thus appear in the document title. You might want to create a blacklist based on the name

definition, or maybe parent

.

+2


source







All Articles