Refactoring a DataTable with a large number of attributes - jsf

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?

Related

rowkey attribute in primefaces is not rendered, without selection or selectionMode attribute

I want use the rowkey attribute within a datatable primefaces (for use it in javascript script),
but I've noticed that is necessary set at least the selectionMode or selection attribute,
otherwise the rowkeyattribute (data-rk) is not rendered.
It 's true, or am I wrong?
I did some tests and it seems to be so.
Below an example from the showcase:
(rowkey attribute seems to be always used in combination with the selectionMode or selection attribute)
http://www.primefaces.org/showcase/ui/data/datatable/selection.xhtml
I would need to take advantage of the rowkey attribute without using selectionMode or selection attribute;
you would know how to do?
Or, you know how to set a custom attribute for each row of datatable without using the component p:row;
The only thing that comes to mind is use the rowClass attribute to insert in, the value of a bean property,
as is the case here
http://www.primefaces.org/showcase/ui/data/datatable/rowColor.xhtml
But I wanted to associate the property of the bean to a specific attribute of row without creating a fake class CSS.
thanks in advance
I assume that you want to achieve the presence of 'data-rk' attribute on a <tr> without the rendering of the selection column.
I did some tests and if you put this styling on the then you will not have the selection column but still the 'data-k' attribute:
<p:column selectionMode="multiple" style="display: none;" />
You have to put this tag, but you do not need to place the selection attribute on the <p:dataTable>.
If this is what you are looking for, then this worked for me on Primefaces 6.0 and JSF 2.2

JSF: Custom component in tables not rendered as expected

Is there a suitable solution for the custom component root-issue in the meanwhile?
In short terms, the problem is that using custom components containing of both a label and an input field within a table like
<h:panelGrid columns="2">
<jl:inputField value="#{testBean.value1}"/>
<jl:inputField value="#{testBean.value2}"/>
</h:panelGrid>
... will be rendered within a single row.
A dirty solution would be to place the panelGrid within the component which will cause a rendering of a separate table for each input field. This is most likely the case cause there isn't a bottom-up but a top-down approach when parsing the code.
Do you have any other ideas how to handle this? Custom tags were mentioned in the discussion.

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>

How to do multiple selection in jsf or primefaces dataTable?

I want to try out building a simple grid that has a delete column, consisting of checkboxes, just like the usual one in email.
User can then tick the checkboxes, and press delete, and i can get all the checked records, and delete them one by one.
Im trying to find a way to achieve this, but so far im still in doubt.
These are what i have in mind, each with it's own implementation question, haha :
How to get the checked row indexes ? Using actionlistener for each toggle on each checkbox ? (but how do i pass the clicked index to the actionlistener ?)
Or is there a way where i can get all the grid model, and loop the data to find out which one is checked, just like swing ? (but how do i get the grid model in the jsf bean ?)
Or perhaps i should bind them to a simple list that contains only the checkbox column data ? (but how do i bind each checkbox to the list using indexes ?)
Im currently using primefaces, but i think the JSF solution can also be applied to primefaces datatable.
Please share your thoughts on this !
Thank you !
Isn't this example from Primefaces showcase exactly what you are looking for?
It looks that it is simply adding a column to the p:dataTable this way:
<p:dataTable var="item" value="#{yourBean.allElements}"
selection="#{yourBean.selectedElements}">
<p:column selectionMode="multiple" />
... other columns
</p:dataTable>

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