JSF custom tag wrapper dynamic parameters - jsf

I am trying to create a custom tag that will act as a wrapper to standard components and will define values for some common attributes
For example the custom tag will look like this
<ui:component xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jstl/core">
<rich:datascroller fastControls="false" fastStep="false" maxPages="20" id="#{value}"/>
</ui:component>
Then i will be able to use this tag every time i need a datascroller component like
<my:dataTable id="componentId"/>
My question is whether i can provide my custom tag with attributes that will be "transfered" to the jsf component without specifying each one explicitly. For example consider the following use of my custom component
<my:dataTable id="componentId" pagesVar="books" stepControls="true"/>
and this one
<my:dataTable id="componentId" pagesVar="items" renderIfSinglePage="false"/>
Attributes pagesVar, stepControls, renderIfSinglePage should be passed to the rich:datascroller component. I know i can do something like this
<rich:datascroller pagesVar=#{pagesVar ? pagesVar : ''} stepControls=#{stepControls ? true: false}/>
but i am wondering if there is a way to pass all attributes without specifying each one of them

but i am wondering if there is a way to pass all attributes without specifying each one of them
No, tag attributes does not support any form of inheritance.
You can however simplify your particular example more.
<rich:datascroller pagesVar="#{pagesVar}" stepControls="#{stepControls}" />

Related

How to set HTML5 data attribute in JSF? [duplicate]

I want to add some iOS specific tag attributes to my login-form. If I have a look on my web page source, the attributes autocorrect, autocapitalize and spellcheck aren't there. What is the reason for this? I am using JSF 2.x.
<h:inputText id="user-name" forceId="true" value="#{login.username}" style="width:120px;"
autocorrect="off" autocapitalize="off" spellcheck="false" />
This is by design. You can only specify attributes which are supported by the JSF component itself (i.e. it's listed in the attribute list in the tag documentation). You can't specify arbitrary additional attributes, they will all be plain ignored.
There are several ways to solve this:
If you're already on JSF 2.2+, simply specify it as passthrough attribute:
<html ... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
...
<h:inputText ... a:autocorrect="off" />
(note that I'm using xmlns:a instead of xmlns:p to avoid clash with PrimeFaces default namespace)
Or:
<html ... xmlns:f="http://xmlns.jcp.org/jsf/core">
...
<h:inputText ...>
<f:passThroughAttribute name="autocorrect" value="off" />
</h:inputText>
Create a custom renderer. You can find several concrete examples in below answers:
How to let JSF pass through HTML attributes
Using bootstrap related tags inside JSF2 h:inputText component
How to render a custom attribute of <h:outputLink>?
InputText PrimeFaces not applying maxlength
Adding Custom Attributes to Primefaces Autocomplete Component in JSF

Best way to extend a particular section in JSF multilevel template

I have a multi level JSF template, say layout.xhtml, which extends from number of template which is depicted below.
layout.xhtml -> level3.xhtml -> level2.xhtml ->level1.xhtml
How to extend level1.xhtml and add one extra facelets ( I want 2 facelets overall) say customer-data.xhtml and supplier-data.xhtml ) inherited from level1.xhtml in place of navigation-module, and have all the facelets of layout.xhtml too?
Below is my template/level1.xhtml
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:insert name="navigation-module" />
<ui:insert name="time-module" />
</ui:composition>
I want to get the common template i.e. layout.xhtml I am not getting how to do this.
I believe that you want to add two pages for the navigation-module. Its very easy, just do the below
<ui:composition
template=template/layout.xhtml
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:define name="navigation-module">
<ui:insert name="WEB-INF/customer-data.xhtml" />
<ui:insert name="WEB-INF/supplier-data.xhtml" />
</ui:define>
As long as you provide the correct ui:insert name i.e. in your case it is navigation-module, and in your ui:define you are telling to JSF, please insert these pages in place of navigation-module. Two keypoints to note here are
Make sure you mention your template name i.e. you can see immediate after ui:composition tag, i.e. template/layout.xhtml ( the reason being you want all the template features)
Use the exact name you want to override in ui:define i.e. in your case it is navigation-module
I hope I am clear to you. Incase you need any further clarification please feel free to drop a comment.

PrimeFaces rendered attribute impact on performance

I'm developing a JSF application with PrimeFaces in which i plan to use mainly tabViews (multiple ones). To give you a general idea about how the application is going to work, I have a side menu from which the user should be able to choose "modules" that will display in the center layout as Tabs. Seeing as I have multiple "modules" and there will be more in the future, the solution I've decided on using is writing the code for all the tabs I have in the xhtml and then using the rendered attribute (set to false by default) in order to display them (when the user clicks on the corresponding menu).
Now comes my question, is setting a component's rendered attribute to false equivalent to that component not being there at all (no impact at performance at all)?
Now comes my question, is setting a component's rendered attribute to false equivalent to that component not being there at all (no impact at performance at all)?
It's NOT equivalent. If you set rendered=false, the component is still there in the component tree on the server side. Therefor it costs a little bit performance and memory.
Mojarra also had big performance problems in the past when the component tree is bigger: https://blog.oio.de/2013/05/16/jsf-performance-mojarra-improves-dramatically-with-latest-release/
To use your xhtml page like a template, follow this steps
Step 1 : Create my included page
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
>
<h:form id="form">
...
</h:form>
</ui:composition>
Let say that the name of this page is myTemplate.xhtml
Step 2 : use your template page each time you need it
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="/templates/templateCrb.xhtml"
xmlns:p="http://primefaces.org/ui"
>
<ui:define name="MyContent">
<ui:include src="/pages/.../myTemplate.xhtml">
</ui:include>
</ui:define>
</ui:composition>
In this case i included a complete page, but you can use it in a dialog, a tabView, you can also send parameter to you include element.
You can read more in more informations about include.
Hope that helped you.

Passing data to a JSF facelet

On the 1st page that is displayed in my JSF application, I want to display data from a database in the form of a table. I have a ManagedBean called a ProductList which has an ArrayList of Product Objects, and I want to put all the Products in a table. I am using the jstl c:forEach tags, but for some reason I get a compile error:
Fatal Error: The prefix "c" for element "c:forEach" is not bound.
Am I using the forEach tag correctly?
<c:forEach items="#{productList.allProducts}" var="product">
</c:forEach>
Here are the namespace tags:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
You must define all the namespaces(the h:, f:prefixes of your xml tags) that you use in the page.
The proper definition for xmlns:c is xmlns:c="http://java.sun.com/jsp/jstl/core"
You can have a longer example here: <c:if test> seems to always evaluate true in JSF2 Facelets

JSF 2.0: Passing composite component attribute to inner composite component

I have the following case:
<cc:interface>
<cc:attribute name="someValue" />
</cc:interface>
<cc:composite>
<x:someComponent>
<span>#{cc.attrs.someValue}</span>
</x:someComponent>
</cc:composite>
So inside my composite component I am calling some other composite component and trying to pass the parameter given to the "master" composite component to the inner composite component.
This fails, because inside x:someComponent tags the cc implicit object seems to refer to this x:someComponent instead.
A workaround is to create a temporary field for the x:someComponent so this can be achieved as:
<x:someComponent passthroughField="#{cc.attrs.someValue}">
<span>#{cc.attrs.passthroughField}</span>
</x:someComponent>
However that's very ugly and unconvenient.
Any other ways around this problem?
One way to hack around this is to use ui:param as in:
<ui:param name="foo" value="cc.attrs.someValue" />
<x:someComponent>
<span>#{foo}</span>
</x:someComponent>
See more in another question.

Resources