Apply converter throughout the whole project - jsf

I would like to apply a converter to all my h:outputText in a project. Is there a way to do it for the whole project, so I don't have to repeat the tag for each field separately?
For example, assume I want the following converter.
<f:convertNumber type = "number" />
Is there a way not to repeat this for every h:outputText field that contains numeric values?

I'm afraid but this is not possible.
But you could write your own JSF outputText Component. That's pretty easy:
https://www.logicbig.com/tutorials/java-ee-tutorial/jsf/custom-component-basic.html

Related

Global date/boolean formatting in frontend of JSF application

I am developing a JSF dashboard web application which includes several very large PrimeFaces datatables. It would be really handy if I could set a global format for the representation of certain types – currently the only way I can think of is having backing bean methods like
public String formattedBoolean(Boolean inputBoolean) {
return inputBoolean ? "Yes" : "No";
}
which I could then manually call from the frontend (and similarly, I could use f:convertDateTime components for formatting date objects as string). However, this type of approach would require adding a lot of boilerplate XHTML, such as
<p:column headerText="Start Date" id="startDate"
sortBy="#{dataContainer.startDate}"
filterBy="#{dataContainer.startDate}">
<h:outputText value="#{dataContainer.startDate}">
<f:convertDateTime pattern="yyyy-MM-dd"/>
</h:outputText>
</p:column>
which I'd rather avoid. Does anyone know if there is a more elegant way of globally overriding the default Java string representation of objects in the frontend, or at least within the context of a data table?
Following advice above, I have decided to override the default FacesConverter for the given classes, as these are formats I'd want to present consistently in text throughout the application.

Refactoring a DataTable with a large number of attributes

I've got a data table with 17 attributes. The table can be rendered in two modes: with row selection enabled and without it.
<p:dataTable selection="#{isDefaultSelectionMode ? null : widget.selected}" />
It doesn't work because selection expects a reference to a property to be able to set/get it.
I could create a dummy property widget.ignored and it's going to work. I don't like this for the obvious reason.
<p:dataTable selection="#{isDefaultSelectionMode ? widget.ignored : widget.selected}" />
I could split the table into two separate templates. I would exclude selection from one and duplicate 16 other attributes. It's not a good one, either.
I am looking for an elegant solution to either make the attribute optional (not to render it under some condition) or to avoid defining a dummy property.
I am new to JSF and PrimeFaces, feel free to correct. Any help would be welcomed.
Fortunately, I didn't have to apply any of my terrible workarounds.
As suggested by #Kukeltje (thank you) and the links he provided, I defined the attribute conditionally
<c:if test="#{isDefaultSelectionMode}">
<f:attribute name="selection" value="#{widget.selected}"/>
</c:if>
For more details, visit these questions:
JSF 2.0 dynamic attributes without creating new components
How not to set an attribute of a component inside a composite component if it is empty?
What is f:attribute used for in this example?

How to define <p:calendar> pattern to entire application?

I would like to define the p:calendar pattern to the entire application instead of to put pattern="dd/MM/yyyy" in each p:calendar.
What I did was overload the renderer for the calendar component with my own and set it there.

Seam conditional render without parsing

I'm trying to make a conditional render in my Seam application (2.2.0), to display two different controls depending on a condition.
I'm using the s:fragment tag with the render attribute, but my problem is that I want whatever the control is displayed, to have the same id:
<s:fragment render="${editable}">
<rich:calendar id="entityDate"..../>
</s:fragment>
<s:fragment render="${!editable}">
<h:outputText id="entityDate".../>
</s:fragment>
My problem is that even when the render attribute set to false, the "not to be rendered" element is parsed, and I get an exception because of the duplicated id.
I also tried with the tag <ui:remove>, which effectively removes the element before the parsing phase, so I can have something like:
<span id="myId"/>
<ui:remove>
<span id="myId"/>
</ui:remove>
Unfortunately the <ui:remove> tag doesn't allow conditional logic. Has anyone found a way to solve this?
That's only possible when you use a view build time tag such as JSTL <c:if>.
<c:if test="#{editable}">
<rich:calendar id="entityDate" />
</c:if>
<c:if test="#{!editable}">
<h:outputText id="entityDate" />
</c:if>
(note that this is not going to work within an iterablte JSF component, such as <ui:repeat>, <h:dataTable> and so on)
After all, I strongly recommend to take benefit of the disabled attribute instead, if necessary with a good shot of CSS to hide the input field borders and so on. It'll minimize the JSF view boilerplate code.
<rich:calendar id="entityDate" disabled="#{!editable}" />
Disabled inputs are separately styleable by the CSS attribute selector element[attribute], e.g.
input[disabled] {
border: 0;
}
The above removes the border of input elements with the disabled attribute present so that it look like a normal output text.
"Solve"? There is nothing to solve here: two elements in a GUI can not have the same ID. Hardly unnatural or unsound?
It's like asking: "I have a database table with two rows, I would like them both to have the same primary key value, but somehow I get these errors... has anyone managed to solve the problem and circumvent the constraints?".
Or even closer analogy: "I have two spans, one of them is invisible (has style="display: none") I would like them both to have the same id - and browsers seem not to like it, despite one of the spans being invisible".
Bottom line: rendered on not rendered, each component is still a part of the view tree, and therefore has a UNIQUE id.
I have a suspicion that you want to have some "polymorphic" code that should work with the currently visible element. Using ID for such code IS WRONG. If you show us your use case, we might find a right way to achieve the effect.
I use selenuim myself in a seam environement and i recommend using defined ids whenever possible. First you have the ability to create smaller ids which is usefull for pagesize. Second the selenium test run alot faster if you use ids for referencing instead of other selectors. I have not yet found a selenium test where you cannot handle diffrent ids. Additionally if a code fails in jsf tree creation you see which id is failing.
I see you are using sfragment with editable or not. I use the sdecorate and give the decorate an id and then "just" ed for the input and vi for the outputtext for example. This makes it easy in selenium to check the availability of edit or view components.
Would you be able to get the same results you need by putting the id tag on the fragment?
So:
<s:fragment id="entityDate">
<rich:calendar render="${editable}" />
<h:outputText render="${!editable}" />
</s:fragment>

JSF composite:insertFacet and composite:renderFacet

I want to have a composite component with a facet in it, which I implement in my "implementation" of this composite component. My problem are ids, because when I only define in my composite component and then with put my implementation in it, it only renders it but the component is in another place.
Here is a sample code:
myComposition.xhtml
<composite:implementation>
<composite:renderFacet name="myFacet">
</composite:implementation>
myCompositionImpl.xhtml
<mySomething:myComposition>
<f:facet name="myFacet">
this code is rendered but the "component" which I define here is not placed
logically in the place where I defined the "renderFacet".
</f:facet>
</mySomething:myComposition>
What can I do about this? With composite:insertFacet it doesn't render anything. I need to have the component also there because I need to know the client id of it.
Just to clarify:
Did you specify <cc:facet name="myFacet"> within the interface of the component?
Furthermore what exactly do you mean with in another place?
Some tips:
renderFacet is correct, insertFacet is for facets defined within the composite itself.
Try adding "<!-- -->" as the first line of content of your facet, this suppose to be a workaround for a bug regarding single line facet content.
I got it working. The problem was I had to figure out the clientId of the facet inserted and I didn't know that each composite-component makes it own NamingContainer.
I had something like that:
"myComposition2.xhtml"
...
"index.faces"
and the resulting clientId was: myC2:myC1:

Resources