h:dataTable inside ui:repeat, how specify render id from f:ajax? - java

I have:
<ui:repeat id="projectsTable" var="project" value="#{projectsBacking.projectList}">
#{project.id}
<h:dataTable id="usersAssignedToProject#{project.id}" var="appUser" value="#{projectsBacking.getAllUsersAssignedToProject(project)}">
#{project.id}
<h:column>
<h:outputText value="#{appUser.getUsername()}"/>
</h:column>
</h:dataTable>
</ui:repeat>
Using <f:ajax> I can not render h:dataTable with given id, can someone explain me what is wrong in this code? When I checked by FireBug <table id="usersAssignedToProject">, but in client side #{project.id} was printed (before and inside datatable).

It is because of id of h:dataTable is resolved when components tree is being build, but var project is only available on render response.
Try using c:forEach in this case instead of ui:repeat.
More information on this:
https://rogerkeays.com/jsf-c-foreach-vs-ui-repeat

Related

PrimeFaces filling dataTable with List<Object> inside another List<Object>

UPDATE:
I found that the issue with the dataGrid not looping through a list inside a list was an issue on the XML code side. Now the dataGrid is reading the List and looping through it creating panels based on the name. The issue now seems to be accessing certain properties in this List.
<p:dataGrid value="#{objList.objList2}" var="objList2" columns="1">
<p:panel id="obj2" header="#{objList2.name}" toggleable="true" collapsed="false">
<h:panelGrid columns="2" style="width: 100%" columnClasses="scenario-viewer-leftcolumn,scenario-viewer-rightcolumn">
<h:outputText value="Output Name:" />
<p:inputText value="#{objList2.objType}" styleClass="textBoxStyle"/>
<h:outputText value="Output Bool:" />
<p:selectBooleanCheckbox value="#{objList2.boolVar}"/>
</h:panelGrid>
</p:panel>
</p:dataGrid>
</p:panel>
</p:dataGrid>
When I try to access a variable under objList2 is gives me the error saying The class obj2 does not have a readable property 'objType'. I double checked and it does have this property/variable and it is initialized.
What makes this even more strange is if I use objList2.boolVar in place of objList2.name in the header for each panel, it displays the information fine. This proves that the property exists and is initialized. Why wouldn't this work in inputText?? Any help would be greatly appreciated.
ORIGINAL:
I am working with PrimeFaces and trying to create a xhtml form for my UI. I am trying to dynamically display data from a list into a dataGrid structure. I am able to do this successfully, but I also need to display data from a list inside the first list.
For example:
I have a List under the variable objList which I use for my first dataGrid. I am able to loop through this list and create panels for each object and some other String data per object.
<p:dataGrid value="#{scenarioTree.objList}" var="objList" columns="1">
<p:panel id="obj" header="#{objList.name}" toggleable="true" collapsed="true">
<h:panelGrid columns="2" style="width: 100%" columnClasses="scenario-viewer-leftcolumn,scenario-viewer-rightcolumn">
<h:outputText value="text:" />
<p:inputText value="#{objList.variable}" styleClass="textBoxStyle"/>
<h:outputText value="text2:" />
<p:inputText value="#{objList.variable2}" styleClass="textBoxStyle"/>
</h:panelGrid>
Now I want to be able to create a second dataGrid that refers to objList2 which is inside objList1. Doing this though returns No records found in the UI even though there is a bunch of records there.
<p:dataGrid value="#{objList.objList2}" var="objList2" columns="1">
<p:panel id="obj2" header="#{objList2.name}" toggleable="true" collapsed="false">
</p:panel>
</p:dataGrid>
</p:panel>
</p:dataGrid>
Is this a bug with PrimeFaces or am I not able to do this? Or am I doing this wrong?
whenever we are talking about iterating list in xhtml we have dataTable,dataGrid, etc and panelGrid also becoz dataTable and all others are child of panelGrid(we can say this becoz panelGrid is also going to form table and others as well i meant child from this way) so in this case try to iterate the inner list in panelGrid since you are using panelGrid and referring variable is list so internally jsf is going to understand like this:
objList.get(i).getVariable();//For the first row
but according to your code it is understanding like this:
objList.getVariable();
which is not at all present so it is giving issue take out panel i don't find it's use and use like this:
<p:panelGrid value="#{objList}" var="obj">
//Access properties inside that
</p:panelGrid>
you can use <f:facet> tag if you want something in header

primefaces filterby function gives no results

I am trying to filter a datatable by adding the following code:
<p:dataTable value="#{hoofdschermBean.onderzoekers}" widgetVar="onderzoekerTable" var="onderzoekeritem" rendered="#{not empty hoofdschermBean.onderzoekers}" rowStyleClass="tablerow" draggableColumns="true">
<f:facet name="header">
<p:outputPanel>
<h:outputText value="Zoeken:" />
<p:inputText id="globalFilter" onkeyup="PF('onderzoekerTable').filter()" style="width:150px" placeholder="Enter keyword"/>
</p:outputPanel>
</f:facet>
However it does not filter when I fill something in this textbox, it says no records found.
If I add filterBy on a column, only than this textbox can filter on the column variable. What am I doing wrong here?
(P.S. I do not want to have filter functions on every separate column, that is why I wanted this facet only!)
#Edit 14:32 27-11-2014
I have also tried to use
filteredValue="#{hoofdschermBean.gefilterdeOnderzoekers}"
and to use ViewScoped and SessionScoped.
Do you have a List<> field in your managedBean so the filtered values can be saved somewhere? Also, you'd need to reference this value with a filteredValue="#{hoofdschermBean.filtered...}"attribute in your dataTable-Tag.
(Like in the PrimeFaces ShowCase, where they have a List<Car> filteredCars; in their managedBean)
Also, it might be helpful to check the scope of your ManagedBean

JSF p:commandLink and p:ajax have different behavior in update

I have a menu with list items and a p:commandLink inside. While using this for different pages I realized that I have problems updating form with a p:dataTable and p:columns inside. After clicking on the link, form2 which actually has some panels and the table inside should be updated. Now my problem: Only most of the content in form2 is updated correctly, but the p:columns have the old value. If I click again on the link, the correct values are shown.
The bean method public void selectProject(Project myProject) is called correctly and the values are correctly processed.
Now the strange thing: If I add a h:graphicImage with a p:ajax everything works fine!!
<h:form id="form1">
...
<li>
<p:commandLink update=":form2" actionListener="#{bean.selectProject(p)}">
<h:outputText value="#{p.name}" />
</p:commandLink>
<!-- Code below is for testing only, but works fine! -->
<h:graphicImage value="#{iconBean.icon(12,'clock')}">
<p:ajax event="click" update=":form2" listener="#{bean.selectProject(p)}"/>
</h:graphicImage>
</li>
...
</h:form>
Update This does not seem to be related to p:columns, a simplified test case shows the expected behavior of p:commandLink. In the original (still failing) setting the menu is implemented as a composite component.
As a workaround I use
<h:commandLink>
<h:outputText value="#{p.name}"/>
<p:ajax event="click" update=":form2" listener="#{bean.selectProject(p)}"/>
</h:commandLink>

Rules for ids to update components

I'm new to JSF2 and Primefaces and realized an issue to update components.
Lets' assume I have the following piece of code, I can directly update="counter"
<h:form id="f1">
<h:outputText id="counter" value="#{clientBean.counter}" />
<h:graphicImage url="/images/circle-ok.png">
<p:ajax event="click" update="counter" process="#this"
listener="#{clientBean.tag}"/>
</h:graphicImage>
</h:form>
In another h:form I have to use update="f1:counter". Only a update="counter" does not work here.
<h:form id="f2">
<p:dataTable var="var" value="#{clientBean.vf}">
<p:column>
<f:facet name="header">Tag</f:facet>
<h:graphicImage url="/images/circle-ok.png">
<p:ajax event="click" update="f1:counter" process="#this"
listener="#{clientBean.tag}" />
</h:graphicImage>
</p:column>
</p:dataTable>
</h:form>
I haven't faced this with JSF1.2 (and RichFaces), what are the rules to address the ids correctly?
In your first example JSF could lookup up the counter element in the same scope as ajax listener. Form implements NamingContainer which means it prefixes client ids (used in html) with its own id and creates a distinct name space for ids. Have a look at the page source under browser - there will be f1:counter id assigned to your counter. In your second example there is no counter element in the scope (inside form f2) so the lookup fails.
You can disable this form behaviour with prependId="false". This is useful if you are sure there won't be elements with identical ids across all forms.
Icefaces works differently - it automatically calculates the html delta and sends it to the browser as partial update. In most cases this is more convenient for the programmer but comes with considerable performance cost. I believe JSF2 adopted icefaces partial updates concept but requires ids to be passed explicitely.

How to refer to dataTable parent within the dataTable?

Consider a dummy case:
<h:form id="wrapperForm">
<h:panelGroup id="rowsContainer">
<h:dataTable id="rowsTable" value="#{bean.rows}" var="row" >
<h:column>
<h:commandButton value="Click me to update (#{component.parent.parent.parent.clientId})">
<f:ajax render=":#{component.parent.parent.parent.clientId}" />
</h:commandButton>
</h:column>
</h:dataTable>
</h:panelGroup>
</h:form>
On button click, the id=rowsContainer gets successfully updated as it should.
However, if I add ui:repeat there, it does not work anymore:
<h:form id="wrapperForm">
<ui:repeat id="blocksRepeat" var="block" value="#{bean.blocks}">
<h:panelGroup id="rowsWrapper">
<h:dataTable id="rowsTable" value="#{block.rows}" var="row" >
<h:column>
<h:commandButton value="Click me 2 update (#{component.parent.parent.parent.clientId})">
<f:ajax render=":#{component.parent.parent.parent.clientId}" />
</h:commandButton>
</h:column>
</h:dataTable>
</h:panelGroup>
</ui:repeat>
</h:form>
Instead, this gets:
<f:ajax> contains an unknown id ':wrapperForm:blocksRepeat:0:rowsWrapper' - cannot locate it in the context of the component j_idt363
However, that component is really there with that ID, so the EL should be ok. Somehow the ui:repeat breaks the case. Is it possibly trying to evaluate the EL before the actual loop?
How do you refer to the rowsWrapper element from within the dataTable?
Note: I recently asked about odd dataTable naming within ui:repeat, which turned out to be a bug. This issue should not be related to that, however, as I am wrapping the dataTable within a panelGroup as suggested here.
There are actually two things going wrong:
1) ui:repeat is broken
As answered by BalusC in the comments of the question, the first issue occurs (once again) due to a bug in Mojarra. It seems ui:repeat is so broken even the wrapper container holding the h:dataTable does not help. For more details, see question "Why doesn't h:dataTable inside ui:repeat get correct ID?" and the comments of this question.
As BalusC suggests, a workaround is to use h:dataTable instead of ui:repeat. It will provide unconvenient (<table>) HTML but works. This removes some odd issues when adding and removing rows to/from the inner iteration.
Note: some issues regarding ui:repeat seem to be fixed in Mojarra 2.0.3 but not all.
2) The references just fail
Even with h:dataTable workaround, the reference to the inner h:dataTable from the button inside it fails. As there is no ui:repeat in use, this must be datatable's internal issue. I don't see any solution at the moment, so I filed a ticket for this behavior as well.

Categories