Generate unique id for h:dataTable in the loop - jsf

I am using JSF 2.0. When I am trying to use a variable in the 'id' attribute of the h:dataTable its not taking that variable value.
I have h:dataTable inside ui:repeat with id values as index of ui:repeat as mentioned below.
<ui:repeat var="planMap" value="#{planAccountMap.entrySet().toArray()}" varStatus="planMapStatus">
<h:dataTable id="planTable#{planMapStatus.index}" value="#{planMap.value}" var="accountList">
Does any one know whether we can have dynamic id generated for h:dataTable in loop?
I have a Java script which is making use of table id, but as I am not able to have the unique id for each table in the loop, its breaking.

Any component inside of a repeatable component will always have a dynamic client id. You cannot do this.
Perhaps instead you can assign a unique style class to the dataTable component and use a jQuery selector to return an array of all the dataTable objects in the ui:repeat.
jQuery('.SomeClass');

I do some thing very similar to you. i have a UI:repeat inside a datatable column. tbh, if you check in fire bug, your datatable id would be unique as you put it inside a ui:repaet.
planMap:0:yourdatatableID

This problem can be solve by using datatable inside datatable. Second datatable is kept inside the column of the first datatable as below.
<h:dataTable id="outerTable" value="#{planAccountMap.entrySet().toArray()}" var="planMap" width="100%">
<h:column>
<h:dataTable id="planTable" value="#{planMap.value}" var="accountList"
headerClass="tablehead"
rowClasses="'',altrowcoloropt1"
first="0">
<h:column>
<f:facet name="header">
<h:outputText value="Date" />
</f:facet>
<h:outputText value="#{accountList.date}"/>
</h:column>
<h:column>
<f:facet name="header" >
<h:outputText value="Account Name" />
</f:facet>
<h:outputText value="#{accountList.accountName}"/>
</h:column>
</h:dataTable>
</h:column>
</h:dataTable>
By this you would get unique id as outerTable:0:planTable, outerTable:1:planTable.This even extend the unique id to each element in datatable as outerTable:1:planTable:1:columnid , outerTable:0:planTable:0:columnid

Related

Column header not visible when column is conditionally rendered

I have a h:dataTable. I would like to render a row conditionally as follows:
<h:dataTable value="#{myController.entities}" var="entity">
<h:column rendered="#{entity.selected}">
<f:facet name="header">
<h:outputText value="header" />
</f:facet>
<h:outputText value="#{entity.name}" />
</h:column>
</h:dataTable>
In my controller there is variable List <Entity> entities which has getters and setters.
Entity class contains two variables : boolean selected and String name with its getters and setters.
When #{entity.selected} is false, then the row is hidden. When #{entity.selected} is true, then the row is shown, but without header. When I do not use the rendered attribute on the column my header becomes visible.
This question is similar to p:column header facet is not shown when rendered attribute is used on p:column
But none of the solution given works for me and Iam not using primefaces.
Can somebody help me with this? Iam new to JSF and the mistake might be something silly and fix fairly easy, but please help me figure it out. Thanks.
Iam posting the outputs that I get when I tried the above code.
**Header**
name 0
name 1
name 2
name 3
name 4
This output shows the datatable using simply <h:column> without trying to render it conditionally. The header can be seen.
Now when I use conditional rendering:
name 1
name 3
In this output Iam trying to use conditional rendering <h:column rendered="#{entity.selected}">. As you can see that for "name 0", "name 3" and "name 5" the #{entity.selected} is false and hence its not rendering.
This is exactly what I need but only if the header shows up.
I want to render my row invisible where the #{entity.selected} value is false. Also show the column header. Can this be possible?
You need to put the rendered condition on the cell, not on the column.
<h:dataTable value="#{myController.entities}" var="entity">
<h:column>
<f:facet name="header">
<h:outputText value="header" />
</f:facet>
<h:outputText value="#{entity.name}" rendered="#{entity.selected}" />
</h:column>
</h:dataTable>
Or, if you've multiple components or plain text representing cell content, wrap it in a <h:panelGroup> or <ui:fragment>.
<h:dataTable value="#{myController.entities}" var="entity">
<h:column>
<f:facet name="header">
header
</f:facet>
<h:panelGroup rendered="#{entity.selected}">
Blah blah #{entity.name} blah blah
</h:panelGroup>
</h:column>
</h:dataTable>
(note: you don't necessarily need h:outputText over all place, see also Is it suggested to use h:outputText for everything?)
Apply if necessary the following CSS on the table to hide empty cells in case you've applied e.g. borders or bgcolors on table cells:
table {
empty-cells: hide;
}
A completely different alternative is to provide a new model which contains only the desired entities:
<h:dataTable value="#{myController.selectedEntities}" var="entity">
<h:column>
<f:facet name="header">
header
</f:facet>
#{entity.name}
</h:column>
</h:dataTable>
Instead of
...
<f:facet name="header">
<h:outputText value="header" />
</f:facet>
...
try simply
...
<f:facet name="header">Header</f:facet>
...

Two buttons ( that generate inputtexts when clicked ) don't work on the same Facelet

I have two buttons that generate inputtexts when clicked. The problem is, when these two buttons are on the same xhtml, wichever is the first one, it is the only one that works.
If you need, here is an explanation on the Code 1 below:
It represents two inputtexts to get the name
and email of the author of a Document. moreAuthors represents
the method getMoreAuthors() that belongs to the Managed Bean inserirBean.
getMoreAuthors() returns a List<AuthorBean>.
The List<AuthorBean> is a property from the Managed Bean inserirBean.
The class AuthorBean creates the instances of Author, it has a property called
Author author.
AddAuthor() adds one more AuthorBean to the List<AuthorBean> in
Managed Bean inserirBean.
If you need, here is an explanation on the Code 2 below:
It follows the same structure from Code 1. Here, there's only one
inputtext that is used to get a subject of a Document.
moreSubjects returns a List<SubjectBean>. The class SubjectBean
creates the instances of the class Subjects.
SubjectBean has a property Subject sub,
and Subject has a property called String subject.
AddSubject() adds one more SubjectBean to the List<SubjectBean> in
Managed Bean inserirBean.
Code 1- If this is the only one on the xhtml, it works:
<h:form >
<h:dataTable value="#{inserirBean.moreAuthors}" var="authorBean">
<h:column>
Nome do Autor:
<h:inputText value="#{authorBean.author.name}" />
</h:column>
<h:column>
Email do Autor:
<h:inputText value="#{authorBean.author.email}" />
</h:column>
<f:facet name="footer">
<h:panelGroup>
<h:commandButton value="+" action="#{inserirBean.addAuthor()}" />
</h:panelGroup>
</f:facet>
</h:dataTable>
</h:form>
2- If this is the only one on the xhtml, it works too:
<h:form >
<h:dataTable value="#{inserirBean.moreSubjects}" var="subjectBean">
<h:column>
Palavras-chave:
<h:inputText value="#{subjectBean.sub.subject}" />
</h:column>
<f:facet name="footer">
<h:panelGroup>
<h:commandButton value="+" action="#{inserirBean.addSubject}" />
</h:panelGroup>
</f:facet>
</h:dataTable>
</h:form>
BUT, if I put these two blocks on the same xhtml, the one that appears first on the browser, always works, and the second, never - and I've already tried to change their position, but whichever I put first place on screen is the one that works.
What's causing this problem?
Thank you!
I just put the two datatables in code 1 and 2 inside the same <form> block and both worked.

jsf tabledata dynamic inputtext

I have a List in my backing bean. I want to present it in a table. I want table to have two rows - on left side, values from the list, and on the right side inputBoxes. It's the easy part. Here's my code:
<div class="table">
<h:dataTable id="korekty" styleClass="table table-hover"
value="#{searchBean.listX}" var="v">
<h:column>
<f:facet name="header">XXX</f:facet>
#{v.string}
</h:column>
<h:column>
<f:facet name="header">YYY</f:facet>
<h:inputText styleClass="form-control">
</h:inputText>
</h:column>
</h:dataTable>
</div>
The hard part of my problem is : in those inputtext user might put some numbers. Then after hitting SUBMIT button I want to create a list/map/whatever of inputed values. How can I do that? Thanks for help
First of all, prepare an array, or a list, containing placeholders for the given data alongside the list you've got:
List<String> initialData = ...;//initial data of n size
String[] submittedData = new String[initialData.size()];//array of the same size
Then, bind the <h:dataTable> component to the view to get access to the current row index of the iteration. This way you can finish your job by binding value of input elements to the corresponding objects in the array/list:
<h:dataTable binding="#{table}" ... >
<h:column>
<f:facet name="header">YYY</f:facet>
<h:inputText value="#{searchBean.submittedData[table.rowIndex]}" ... />
</h:column>
</h:dataTable>

CommandLink with parameter in actionListener method doesn't work inside f:facet of datatable

I'd like to be able to click the headers in a table to sort the respective columns. When I try to do this with a h:commandLink and pass the column name as a parameter I get an error saying that the commandLink needs to be ended with > or />, which I do. Example:
<h:column>
<f:facet name="header">
<h:commandLink
value="name"
actionListener="#{albumListBean.sort("album_name")}">
</h:commandLink>
</f:facet>
<h:outputText value="#{item.name}" styleClass="tableItem" />
</h:column>
I get the same result using f:ajax or p:commandLink. If I remove the parameter however, I get no error (but of course the sorting doesn't work either).
Is it not allowed to pass a parameter this way inside the f:facet?
The strings inside EL expressions must be expressed inside simple cotes :
<h:commandLink
value="name"
actionListener="#{albumListBean.sort('album_name')}">
</h:commandLink>

rich:dataScroller index refers previous dataTable scroller index inside a4j:repeat

I am using rich:dataTable inside the a4j:repeat.
Every time the dataTable Scroller refer the index from the previous dataTable scroller index value. So the current dataTable having values but it displays empty table.
Because of,
previous dataTable list size is 200.
previous dataTable scroller index is 7
Current DataTable list size is 5.
<a4j:repeat value="#{Bean.outerTOList}" var="sampleValue">
<rich:dataTable id="dataTable"
var="innerTo"
rows="5"
value="#{sampleValue.sampleInnerTOList}" >
<f:facet name="header">
<rich:column>
<h:outputText value="Header"/>
</rich:column>
</f:facet>
<rich:column>
<h:outputText value="#{innerTo.name}"/>
</rich:column>
<f:facet name="footer">
<rich:datascroller id="dataTableScrollerId"
ajaxSingle="false" maxPages="3"
page="1">
</rich:datascroller>
</f:facet>
</rich:dataTable>
</a4j:repeat>
I think you have to change the <ui:repeat> to a (JSTL) <c:forEach> (see http://www.crazysquirrel.com/computing/java/jsp/jstl-forEach.jspx) because it has another lifecycle and your implementation using ui:repeat won't work in this scenario.
After doing so you probably also need some kind of "discriminator" for your IDs, because you cannot name all table components the same. You would have to use something like id="datatable0",... id="datatable1" and so on. You can use c:forEach's varStatus="status"property to do so. It has a property which you can use as the counter: #{status.index}

Resources