Custom data types in Facelets JSF 2 Expression Language - jsf

How to display a custom property using facelet expression language?
For example:
<h:outputText value="#{contact.customTypeProperty}" />
where customTypeProperty is of type CustomClass, and I want to display the String returned by its toString()?

That should already be the default behaviour. You don't need to change anything on the given code example, assuming that the toString() method is properly implemented on the CustomClass. However, if it returns HTML, you'd need to add escape="false" to the output text to prevent JSF from auto-escaping it (which it does in order to prevent XSS attacks on user-controlled input):
<h:outputText value="#{contact.customTypeProperty}" escape="false" />
This is however not necessarily the best practice. You should control the presentation in the view side, not in a toString() in the model side. For example, assuming that CustomClass has in turn two properties foo and bar and you'd like to present it in a table:
<h:panelGrid columns="2">
<h:outputText value="Foo" />
<h:outputText value="#{contact.customTypeProperty.foo}" />
<h:outputText value="Bar" />
<h:outputText value="#{contact.customTypeProperty.bar}" />
</h:panelGrid>
If you did this to avoid code repetition, then you should actually be using an include file or a tag file. See also When to use <ui:include>, tag files, composite components and/or custom components?

Related

JSF updating certain parts of a composite component

I want to develope a JSF composite component using PrimeFaces library.
Basically I want to update my composite component. I have read some SO questions about it (JSF updating a composite component or JSF Updating Composite Component (Primefaces)). But in this case I only want to update certain parts of the component.
Here is an example. My component should be a label/message/value-part of a <p:panelGrid /> to get rid of all the noise of the <p:column/>-tags.
<composite:interface>
<composite:attribute name="label" required="true" />
<composite:attribute name="value" required="true" />
</composite:interface>
<composite:implementation>
<p:column>
<!-- label -->
<p:outputLabel value="#{cc.attrs.label}" for="id_inputtext"/>
</p:column>
<p:column>
<!-- message -->
<p:message for="id_inputtext" />
</p:column>
<p:column>
<!-- inputtext -->
<p:inputText id="id_inputtext" value="#{cc.attrs.value}"/>
</p:column>
</composite:implementation>
To use this composite component I can simply put it in a panelgrid like so.
<p:panelGrid>
<p:row>
<mycomponent:columnSet id="c1" label="label" value="hello world"/>
<mycomponent:columnSet id="c2" label="label2" value="hello world2"/>
</p:row>
<p:row>
<mycomponent:columnSet id="c3" label="label3" value="hello world3"/>
<mycomponent:columnSet id="c4" label="label4" value="#{bean.someValue}"/>
</p:row>
</p:panelGrid>
In this case I can not surround the content of the component with an HTML container element like <div/> or <span/> like it is described in the above links. That would result in weird HTML because it would be within the generated table.
What I want to do in the example above is to update the <p:outputLabel/>, the <p:message/> and the <p:inputText/> from outside of the component. In a perfect world I want to update these three components independently from each other (but I guess that is even more complicated than updating all at once).
What I currently do to get this to work is kind of cheating. I create a <composite:attribute name="id" /> and give the three components fixed IDs based on a convention using the composite component id. That works but is pretty poor because using the composite component, one needs to know the inner implementation of the it.
Does anyone have an idea to solve this requirement in a nicer way?
<composite:interface>
<composite:attribute name="id" required="true" />
</composite:interface>
<composite:implementation>
<p:column>
<!-- label -->
<p:outputLabel id="#{cc.attrs.id}_label"/>
</p:column>
<p:column>
<!-- message -->
<p:message id="#{cc.attrs.id}_message" />
</p:column>
<p:column>
<!-- inputtext -->
<p:inputText id="#{cc.attrs.id}_value"/>
</p:column>
</composite:implementation>
EDIT
Thanks for the quick response in the comments.
As to the tag files: Indeed, I must admit that I avoided dealing with tag files because composite components are so much easier to handle, my bad.
Anyway, I just read some stuff, made a quick-and-dirty prototype, but came to the conclusion that (although it might be a good and proper way to use tag files in this label/message/input-situation) I have the same issue as with the composite component: To update the components inside the tag file I need to know the inner implementation of it (that is the same as described in my workaround).
I want to update the composite component/tag file from outside with a «single handle» and treat it as a black box.
If I could wish for a feature I want something to say «do the update» on the composite component/tag file. And within the composite component/tag file I can define which components should be updated if «do the update» is triggered. Something like three separate <div id="#{cc.clientId}"/> surrounding every component I want to update (which obviously is not possible like that).
Because I guess that this is nearly impossible, I would also be happy with a way to update a composite component/tag file as a whole, meaning to update every component within the black box.

Passing dynamic param through bundle.properties to alt text value of graphicImage [duplicate]

I have use case in which I have to use resource bundle to display various texts on UI. Some of these resource bundle entries take paramets (e.g. {0}), for these I use h:outputFormat but sometimes that isn't enough.
e.g.
someMessage=Display this message with param {0}
in a resource bundle.
To display it on xhtml I normally do:
<h:outputFormat value="#{msg['someMessage']}"><f:param value="#{someBean.value}"/></h:outputFormat>
That works well when it's a simple case, but for more complex use cases it isn't enough. For example if I want the 'title' attribute of a commandLink to use the above resource bundle entry:
<h:commandLink action="logout" title="#{msg['someMessage']}">
<f:param value="#{someBean.value}" />
<h:graphicImage library="images" name="image.png" />
</h:commandLink>
which doesn't work. I also tried:
<h:commandLink action="logout">
<f:attribute name="title">
<h:outputFormat value="#{msg['someMessage']}"><f:param value="#{someBean.value}"/></h:outputFormat>
</f:attribute>
<h:graphicImage library="images" name="image.png" />
</h:commandLink>
which also doesn't work since f:attibute doesn't allow children.
Even if there is a hack to bypass this (e.g. using hover component from primefaces) there are other fields that might require a parameterized message.
Does anyone know of a way to use MessageFormat that takes an argument in a non-value field of a JSF component?
You could create a custom EL function for this with which you can ultimately end up like:
<h:commandLink ... title="#{my:format(msg['someMessage'], someBean.value)}" />
You can use the MessageFormat API to perform the job, exactly as <h:outputFormat> is doing under the covers.
An alternative is to create a custom component which does the same as JSTL's good 'ol <fmt:message> which supports a var attribute to export the formatted message into the EL scope.
<my:outputFormat ... var="linkTitle">
...
</my:outputFormat>
<h:commandLink ... title="#{linkTitle}" />
Update: JSF utility library OmniFaces has #{of:formatX()} functions and a <o:outputFormat> component for the very purpose.

Is it possible to do dynamic column ordering on a p:dataTable without using p:columns?

I'm trying to dynamically display the columns of a p:dataTable: the server dictates which columns are displayed and in which order. It doesn't look like I can set a dynamic order using the regular p:column tag so I'm stuck using the p:columns tag. The problems with the p:columns tag are:
1) The example in the showcase shows it working with String data, where you can map a column name to a field and then use an expression language map to retrieve the data (like a pseudo-getter)
http://www.primefaces.org/showcase/ui/data/datatable/columns.xhtml
If I have different data types though, then I'm probably stuck with a bunch of panels with render attributes based on the type of the data (display Strings one way, display User objects another way, etc).
Example:
<p:dataTable value="#{myBean.rows}" var="row">
<p:columns value="#{myBean.columns}" var="column">
<f:facet name="header">
<h:outputText value="#{column.header}" />
</f:facet>
<!-- The content of the cell is dynamic based on the type of the field -->
<!-- display a String field -->
<h:outputText rendered="#{myBean.isStringType(column.header)}"
value="#{row[column.property]}"/>
<!-- display a Person field -->
<h:outputText rendered="#{myBean.isPersonType(column.header)}"
value="#{row[column.property].name}, #{row[column.property].email}"/>
</p:columns>
</p:dataTable>
2) p:columns only supports a single sortFunction/filterFunction for all columns. Since these columns all have different types of data, they will require many different sorting and filtering methods
A p:column easily allows for the display of different data types as well as the sorting/filtering of the data. The only thing it can't do is have a dynamic order.
Unless I'm missing something? Is there a way to get this to work with p:column ? Or is there an elegant way to have p:columns handle all of this?
It doesn't look like I can set a dynamic order using the regular p:column tag so I'm stuck using the p:columns tag.
If the #{myBean.columns} columns model is constant during at least the view scope, then you'd better use <c:forEach><p:column><c:choose>. It's faster than <p:columns>+rendered, and allows more dynamic freedom as you can declare every <p:column> individually depending on the type instead of having only one <p:columns> whose state changes every iteration round.
<p:dataTable value="#{myBean.rows}" var="row">
<c:forEach items="#{myBean.columns}" var="column">
<c:choose>
<c:when test="#{column.type eq 'STRING'}">
<p:column sortBy="#{row[column.property]}" filterBy="#{row[column.property]}">
#{row[column.property]}
</p:column>
</c:when>
<c:when test="#{column.type eq 'PERSON'}">
<p:column sortBy="#{row[column.property].name}" filterBy="#{row[column.property].name}">
#{row[column.property].name}, #{row[column.property].email}
</p:column>
</c:when>
...
</c:choose>
</c:forEach>
</p:dataTable>
See also:
JSTL in JSF2 Facelets... makes sense?
How to create dynamic JSF form fields

Passing EL method expression as attribute of custom Facelets tagfile

I created a custom JSF tag:
<ui:composition>
<h:panelGroup>
<rich:dataScroller id="#{id}" for="#{table}" execute="#{table}"
page="#{scrollerPage}" render="#{table}-sc1" maxPages="5"
fastControls="hide" oncomplete="#{onCompl}" scrollListener="#{scrollListenerBean[scrollListenerMethod]}" />
<h:inputText value="#{scrollerPage}" id="#{table}-sc1" size="2">
<f:convertNumber integerOnly="true" />
</h:inputText>
<h:outputText styleClass="outputText"
value=" of #{scrollPagesCount} " />
<h:commandButton value="GO! " />
</h:panelGroup>
</ui:composition>
To pass the listener method, I used the solution suggested in a quite old blog:
<my:dataScroller id="idDS1" table="table1"
scrollerPage="#{bean.navigationHelper.scrollerPage}"
scrollPagesCount="#{bean.navigationHelper.scrollPagesCount}"
onCompl="initForm();"
scrollListenerBean="#{bean}"
scrollListenerMethod="aMethod" />
My questions are: is this the best way to do this? How can I make the method optional?
Thanks a lot for any Help! bye!
My questions are: is this the best way to do this?
That's the only way anyway, provided that you can only use standard JSF/EL facilities and you cannot create a custom taghandler.
You could however create a custom taghandler to convert the value expression to a method expression. The OmniFaces JSF utility library has a <o:methodParam> for exactly this purpose. See also the <o:methodParam> demo page.
You could then end up like:
<my:dataScroller ... scrollListener="#{bean.aMethod}" />
and
<o:methodParam name="scrollListenerMethod" value="#{scrollListener}" />
<rich:dataScroller ... scrollListener="#{scrollListenerMethod}" />
See also:
Dynamic ui include and commandButton
How can I make the method optional?
Theoretically, you could use JSTL tags to build the view conditionally. Something like:
<h:someComponent>
<c:if test="#{not empty fooAttribute}">
<f:attribute name="foo" value="#{fooAttriubte}" />
</c:if>
</h:someComponent>
But that's in the particular case of a special method expression listener attribute unfortunately not possible. There's no such thing as <rich:scrollListener> or something which allows you binding a RichFaces specific scrollListener as a separate tag to the <rich:dataScroller>. Best what you could do without creating custom taghandlers is duplicating the whole <rich:dataScroller> in two <c:if>s (or a <c:choose>); one with and other without scrollListener. This is too clumsy. You'd really better create a custom <my:richScrollListener> taghandler for this which you could then place in a <c:if>.

Seam validation question - check for at least one field filled

I have a situation in my form that the user must fill at least one of the fields. Using "required" command, i cannot do that. What is the best way to validate this in seam ? i dont want to use javascript.
Thanks!
Just let the required attribute depend its outcome on the presence of the other input fields in the request parameter map.
<h:form id="form">
<h:inputText id="input1" value="#{bean.input1}" required="#{empty param['form:input2'] and empty param['form:input3']}" />
<h:inputText id="input2" value="#{bean.input2}" required="#{empty param['form:input1'] and empty param['form:input3']}" />
<h:inputText id="input3" value="#{bean.input3}" required="#{empty param['form:input1'] and empty param['form:input2']}" />
</h:form>
Alternatively you could also make use of component binding and use UIInput#getValue() to check the value of the previous components and UIInput#getSubmittedValue() to check them for the yet-to-be-validated components (components are processed in the order as they appear in the component tree). This way you don't need to hardcode client ID's. You only need to ensure that binding names doesn't conflict with existing managed bean names.
<h:form>
<h:inputText binding="#{input1}" required="#{empty input2.submittedValue and empty input3.submittedValue}" />
<h:inputText binding="#{input2}" required="#{empty input1.value and empty input3.submittedValue}" />
<h:inputText binding="#{input3}" required="#{empty input1.value and empty input2.value}" />
</h:form>
JSF2 will let you do a form-level validation. For now, you'll have to make do with either:
Validate in a Bean after form
submission and populate a
FacesMessage to the user if it fails.
Add a validator to one field and in
that validator load in the other
fields and check their values.
If you dont want to use required attribute or javascript, then there are two ways.
One of them is creating a validator, but in my opinion that is too overkill.
I would just check if the input is null or empty in your bean.
if ("".equals(theFieldYouWantToCheck) || theFieldYouWantToCheck == null) {
//Either throw exception or return "false" so that you can handle it
}
If you are using RichFaces then you could perform the validation as follows (see http://mkblog.exadel.com/ria/richfaces-ria/richfaces-built-in-client-functions/):
<h:form id="form">
<h:inputText id="input1" value="#{bean.input1}" />
<h:inputText id="input2" value="#{bean.input2}"
required="#{empty rich:findComponent('input1').submittedValue}"
requiredMessage="At least one of the fields input1 and input2 must be filled."/>
</h:form>
Note that the expression rich:findComponent('input1') is equivalent to uiComponent['input1']. The reason is that Seam provides the dynamic map uiComponent to look up UI components.

Resources