4

I'm using Primefaces. For some pages I want to exclude the resources which are included by primefacs, especially the theme resource.

<link type="text/css" rel="stylesheet" href="/context/javax.faces.resource/theme.css?ln=primefaces-owntheme" />    

I try that with a SystemEventListener as following:

public class PrimeFacesResourceRemover implements javax.faces.event.SystemEventListener {


  @Override
  public void processEvent(SystemEvent event) throws AbortProcessingException {
    FacesContext context = FacesContext.getCurrentInstance();

    UIViewRoot viewRoot = context.getViewRoot();
    for (UIComponent resource : viewRoot.getComponentResources(context, "head")) {

        Map<String, Object> attrs = resource.getAttributes();
        String resourceLibrary = (String) attrs.get("library");
        String resourceName = (String) attrs.get("name");

        if ("primefaces-owntheme".equals(resourceLibrary) && "theme.css".equals(resourceName)) {

            // Remove resource from view
            context.getViewRoot().removeComponentResource(context, resource, HEAD);
        }
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isListenerForSource(Object source) {
    return (source instanceof UIViewRoot);
  }
}

and in the faces-config.xml

    <application>
      <system-event-listener>
        <system-event-listener-class>
          com.mycompany.mavenproject1.PrimeFacesResourceRemover
        </system-event-listener-class>
        <system-event-class>
          javax.faces.event.PostAddToViewEvent
        </system-event-class>
      </system-event-listener>
    </application>

This works well, when I include a resouce on a page manually, but those not work with the resouces which are included by Primefaces. How can I remove those resouces?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
h2mch
  • 521
  • 5
  • 23

2 Answers2

3

The theme.css is not been added as a dynamic component resource, but it's been hardcoded in PrimeFaces' HeadRenderer. The OmniFaces CombinedResourceHandler was also struggling with this.

The solution is rather simple: override it with a custom HeadRenderer (without any @ResourceDependency on theme.css, of course!):

public class HeadRenderer extends Renderer {

    @Override
    public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
        context.getResponseWriter().startElement("head", component);
    }

    @Override
    public void encodeChildren(FacesContext context, UIComponent component) throws IOException {
        // NOOP.
    }

    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        for (UIComponent resource : context.getViewRoot().getComponentResources(context, "head")) {
            resource.encodeAll(context);
        }

        context.getResponseWriter().endElement("head");
    }

}

Register it as follows in webapp's faces-config.xml:

<render-kit>
    <renderer>
        <component-family>javax.faces.Output</component-family>
        <renderer-type>javax.faces.Head</renderer-type>
        <renderer-class>com.example.HeadRenderer</renderer-class>
    </renderer>
</render-kit>
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • When I understand you right, it is not possible to change the output of a Renderer, without override it? In my case I want to exclude the theme css only when it is a offline page (app.cache). In all other cases, I'm happy with the PrimeFaces HeadRenderer. – h2mch Nov 25 '13 at 12:23
  • You can also extend it instead of overriding, but you would end up with same code anyway. Or are you specifically targeting at those rather useless facets ``, `` and such from the PrimeFaces `HeadRenderer` when you said "I'm happy"? I can't think of any other specific reason why you would explicitly mention that you're happy with it. – BalusC Nov 25 '13 at 12:31
  • Yes I'm using those facets. Specially the last facet to ensure, that I can override the default includes (css). Why you are thinking, that those facets are useless? – h2mch Nov 25 '13 at 12:44
  • Just put those resources in top of ``. Those facets are useless because PrimeFaces completely overlooked this JSF-builtin possibility. See also e.g. http://stackoverflow.com/questions/8768317/how-do-i-override-those-classes-defined-in-primefaces-css/8774997#8774997 – BalusC Nov 25 '13 at 12:49
  • Thx BalusC. I solved my problem in that way. In addition I add a beforePhase-Listener on those page, where I want to remove the theme.css ( ) – h2mch Nov 25 '13 at 15:22
  • @BalusC For me issue is, I need to remove layout.js as i have a omega theme which already have layout.js. the above code helps me to override CSS but how abouty a js file? thanks in advance, – 3bu1 Nov 22 '16 at 11:53
2

For all of you who would like to remove theme.css on all pages (that's the first thing I am doing), and still don't know this trick.

You'll need to drop these few lines in your web.xml:

<context-param>
    <param-name>primefaces.THEME</param-name>
    <param-value>none</param-value>
</context-param>
Kuba
  • 2,069
  • 23
  • 30