JSF 2: duplicate IDs inside p:dataList - jsf

i have a list of billable services per client and i'm trying to build a table where the user can select which ones shall actually be billed:
<p:dataList value="#{billController.billings}" var="billings">
<p:dataTable value='#{billings.billablesDataModel}' var='item' selection="#{billings.toBill}">
<f:facet name="header">
<h:outputText value="#{billings.client.id}" />
</f:facet>
[...]
</p:dataTable>
</p:dataList>
the problem is, that all the dataTables are rendered with the same ID attribute (j_idt9:j_idt13:0:j_idt14) which is automatically assigned by JSF. i'm suspecting this is causing that the selection doesn't work. (the backing bean billings.toBill is not updated/stays empty.)
i was trying to set the ID attribute of the dataTable manually like this:
<p:dataTable id="#{billings.client.id}" ...>
however, i get the following error:
java.lang.IllegalArgumentException: Empty id attribute is not allowed
(#{billings.client.id} is definitely set to the unique client's ID as i get the right output from an h:outputText for debug purposes.)
can you help me fixing this?
i'm using JSF Mojarra 2.1.1 and PrimeFaces 3.2 on a Tomcat 6.

You need to use p:column for content of datalist as documented in user's guide.

What if you loop over billController.billings via ui:repeat and not via p:dataList:
<ui:repeat var="billings" value="#{billController.billings}">
<p:dataTable value="#{billings.billablesDataModel}" var="item" selection="#{billings.toBill}">
[...]
</p:dataTable>
</ui:repeat>

Related

Primefaces 8.0 JSF not updating table [duplicate]

This question already has answers here:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
(6 answers)
Closed 2 years ago.
When I click addTagButton, everything works well. It updates all three components: tags, tagId and addTagButton.
<p:commandButton id="addTagButton" icon="ui-icon-plus"
action="#{searchBean.addTag}"
update="tags, tagId, addTagButton"
disabled="#{searchBean.tagChoices.size() == 0}">
</p:commandButton>
Here's the table component:
<h:dataTable id="tags" var="tag" value="#{searchBean.tags}">
<h:column>
<div style="text-align:right;">
<h:outputLabel value="#{tag.typeName}:"/>
</div>
</h:column>
<h:column>
<p:inputText id="tag" size="25" value="#{tag.typeValue}"
disabled="#{searchBean.searchForParent}"/>
</h:column>
<h:column>
<p:commandButton id="delTagButton" icon="pi pi-trash"
action="#{searchBean.deleteTag}"
update=":contentForm:tagId, :contentForm:addTagButton, tags">
<f:setPropertyActionListener
target="#{searchBean.tagId}"
value="#{tag.typeName}" />
</p:commandButton>
</h:column>
</h:dataTable>
When i click on delTagButton that is on each row in tags table, action works fine, :contentForm:tagId and :contentForm:addTagButton update fine. But tags table which is where clicked command button exist, does not update.
When a row is deleted, change must reflect in the tags table which does not work.
Now, If I change h:dataTable to p:dataTable or any other primefaces component, it works. I am trying to make it work with h:dataTable.
Primefaces 8.0, JSF 2.5
Look on this simple example:
<h:form id="form">
<h:panelGroup id="wrapper" layout="block">
<h:dataTable id="table" border="1" value="#{testBean.list}" var="person">
<h:column>#{person.name}</h:column>
<h:column>#{person.surname}</h:column>
<h:column>
<p:commandButton id="delTagButton" icon="pi pi-trash"
action="#{testBean.remove(person)}" update="table">
</p:commandButton>
</h:column>
</h:dataTable>
</h:panelGroup>
</h:form>
To really find out what is being updated look in browser console.
If you're trying to update="table" nothing happens (like in your code). If you try to update a parent of the table (which is often a case), you will get an error an error:
SEVERE: Error Rendering View[/example.xhtml]
org.primefaces.expression.ComponentNotFoundException: Cannot find component for expression "wrapper" referenced from "form:table:0:delTagButton".
at org.primefaces.expression.SearchExpressionFacade.cannotFindComponent(SearchExpressionFacade.java:677)
So we could try with "older" parent and realize that update="#form" works! OK, so we want to help to find id="table\wrapper" component. Let try clientId update="form:table". Like with update="table" nothing happens. And no error from PF (so the element can be found). This could mean that h:dataTable cannot be properly re-rendered from inside itself (but I don't want to throw stones:-)). This is often a case with e.g. popups in JSF 3rd party component libraries.
In this particular example I'd say, you have to update form:wrapper (adding form: works) or just #form to get it work. With your code it would be the same. Try to update some table parent or the whole form.
All of above is tested in JSF 2.2, with last RF, an old PF and OmniFaces. But I think the same would be the case with newer versions.
BTW. I didn't know there is JSF 2.5 :-)

JSF validation error prevents updating another valid rows of an h:dataTable placed in an h:form

I have an h:dataTable inside of an h:form, where each row has it's own h:commandButton type="submit" action="#{bean.saveChanges(item)}".
f:inputs are declared as required and they also need to match a pattern.
If every input is in the right format, then it works fine.
Otherwise it needs only one input to be wrong and an updating function on a commandButton corresponding to a completely different item in another row seems not to be called, therefore not updated in the database.
Also only the wrong row's validation message is displayed and the changes are maintained in the view by a (backing Spring view scoped) bean, so the user might actually think, that the initial row was indeed updated in the database too.
Is there a way, how to separate individual rows of the h:dataTable, so that the validation messages of another row does not stop other items from being updated by the method of a (Spring/backing) bean?
Use ajax to process/execute only the current row. You can achieve that by explicitly specifying the client IDs of the input components in <f:ajax execute>.
<h:form>
<h:dataTable ...>
<h:column>
<h:inputText id="foo" ... />
</h:column>
<h:column>
<h:inputText id="bar" ... />
</h:column>
<h:column>
<h:inputText id="baz" ... />
</h:column>
<h:column>
<h:commandButton ...>
<f:ajax execute="foo bar baz #this" ... />
</h:commandButton>
</h:column>
</h:dataTable>
</h:form>
This won't process the inputs in other rows. Use if necessary <f:ajax render> to update the <h:message(s)> associated with the inputs.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
The required on the input cause the Process validation to fail and the render response to be invoked.
A simple solution could be You could remove the required from the input and handle the case in you managed bean. Since the action would move on till Phase 5: Invoke application the valid data can be saved. For all invalid rows highlight the row by having a boolean in you data model.

Setting the ID of an inputfield in dynamic columns Richfaces JSF-1.2 when not rendered

I've got dynamic columns. Some have Inputfields others don't.
Why do I have to set the Id of an Inputfield if I don't want to render it?
<rich:columns value="#{columnBean.columns}" var="column" index="ind" id="#{column.id}">
<f:facet name="header">
<h:inputText id="#{column.inputFilterId}" value="#{otherBean.filterValue[column.filterBy]}" onkeyup="filterKeyUp(event)" onclick="Event.stop(event);" />
</f:facet>
<h:outputText value="#{columnBean.lineItemHandler[line]}" rendered="#{columnBean.curCol[column.id]}"/>
</rich:columns>
I'm using JSF 1.2 and Richfaces 3.3.3 Final
I fixed it, just put a unique Id-Value from my Column Bean.
The better solution is to do this:
https://stackoverflow.com/a/18358949/5146922
THX BalusC

Filtering issues (no change in contents) in datatable primefaces 3.5, sorting works

Primefaces 3.5 doesn't seem to filter data at all from the datatable, oddly enough it somehow reorders them as I type, so, there must be some AJAX calls firing, but obviously not the right ones.
<h:panelGroup id="table-wrapper-component">
<prime:dataTable
rendered="#{artifactSelectionBackingBean.visibleComps}"
value="#{artifactSelectionBackingBean.components}"
var="tagInfoObject" emptyMessage="No tags found with given criteria"
filteredValue="#{artifactSelectionBackingBean.filteredComponents}">
<prime:ajax event="filter" global="false" />
<prime:column sortBy="#{tagInfoObject.tagId}"
headerText="Identifier" filterMatchMode="contains" filterBy = "#{tagInfoObject.tagId}">
<h:outputText value="#{tagInfoObject.tagId}" />
</prime:column>
<prime:column sortBy="#{tagInfoObject.type.tagTypeId}"
headerText="Tag Identifier" filterMatchMode="contains" filterBy ="#{tagInfoObject.type.tagTypeId}">
<h:outputText value="#{tagInfoObject.type.tagTypeId}" />
</prime:column>
<prime:column sortBy="#{tagInfoObject.title}" headerText="Title" filterMatchMode="contains" filterBy="#{tagInfoObject.title}">
<h:outputText value="#{tagInfoObject.title}" />
</prime:column>
<prime:column filterBy="#{tagInfoObject.description}"
filterMatchMode="contains" sortBy="#{tagInfoObject.description}"
styleClass="wrap" headerText="Component Description">
<h:outputText value="#{tagInfoObject.description}" />
</prime:column>
</prime:dataTable>
</h:panelGroup>
Any help is appreciated! All the Beans and method calls exist and return the appropriate data, just that the filtering doesn't seem to work at all.
Also, note that sorting functions properly only filtering does not!
The issue was that you always need to wrap any filtering/sorting attributes in a data table with an h:form tag. This is not explicitly specified in the documentation of PrimeFaces, however, it is in the showcase here. I wrapped the whole thing in form tags.
So, don't forget to wrap your data tables in a form if you want any type of interaction provided by primefaces.
Your managed Bean Code will do a lot of good
Post your managed bean code.
May be you have not set the value for artifactSelectionBackingBean.filteredComponents in the managed bean

JSF Primefaces TabView problems

I asked this in the PF Forum but no one seems to want to answer so I though I'd try my luck here.
I have a ui:repeat that is not being updated correctly after an Ajax call when it is within a TabView.
Simple scenario is I have a ui:repeat pointing at an ArrayList (ArrayList contains simple pojos with a String). Within this I have an h:inputText whose value is the pojo's String getter/setter. The ui:repeat is contained within a h:panelGroup. I use a p:commandButton to run an action to update the ArrayList (just add a couple of objects to it a Math.random value for the String) and then update the h:panelGroup. The updated values in the ArrayList are not reflecting in the ui:repeat input fields. This only appears to be affecting input fields as outputText fields do update correctly. Also if I do the same for a p:dataTable the input field are updated correctly. If I remove the Tabview and Tab tags it works fine.
As it works when removing the Tabs I can only assume this is a bug and not designed to work like this. If someone could please confirm if this is so or if there is a viable work around. I need to use a ui:repeat as my fields are not in a tabular format. This has only occurred since migrating from PF 2.2. I'm currently on PF 3.1, Weblogic 10.3.4 and Mojarra 2.0.4
<p:tabView>
<p:tab title="Test">
<h:form prependId="false">
<p:commandButton id="testStringCheck"
value="Test String Check"
process="#form"
update="testPanel"
action="#{testBean.generateVOwithRandomStrings}">
</p:commandButton>
<h:panelGroup id="testPanel" layout="block">
<ui:repeat value="#{testBean.voList}" var="entry">
<h:outputText value="#{entry.randomString}"/>
<p:inputText style="display:block;"
value="#{entry.randomString}"
size="15">
</p:inputText>
</ui:repeat>
</h:panelGroup>
</h:form>
</p:tab>
</p:tabView>
As a workaround I've used a p:datagrid instead of a ui:repeat. This achieves the look I had in the the ui:repeat so I'm happy. Hopefully this bug will be fixed on future releases.
This is something of a bug in Primefaces commandButton. See the following thread:
http://forum.primefaces.org/viewtopic.php?f=3&t=17454
You can try replacing
<p:commandLink id="testStringCheck" ... update="#form" />
With an <h:commandLink>
<h:commandLink id="testStringCheck" render="#form"/>
Also from the above link here is an interesting method that somebody posted that enables you to correctly find the correct clientId to update.
http://paste.kde.org/177698/
temp solution: insert outside h:panelGroup:
<p:outputPanel defered="true" delay="1" ..>
and update outputPanel instead of panelGroup
Or use a datalist component instead of ui:repeat.
One more, i'm not sure but you can try, so update class instead id:
<h:panelGroup id="testPanel" layout="block" styleClass="testPanelCl" ../>
and update : #(.testPanelCl), don't forget id of panelGroup, without id JSF can not update by class

Resources