jsf 2.0 update specific element inside ui:repeat - ajax

I'm asking how I can achieve updating a specific element of a loop?
e.g.
<h:form>
<ui:repeat var="element" value="#{bean.elements}" varStatus="status">
<h:outputtext value="#{element.text}" id="#{element.id}" />
<p:commandLink update="#{element.id}" >
<h:outputtext value="UpdateTextField #{element.id}" />
</p:commandLink>
</ui:repeat>
</h:form>
I know that status.index doen't work since its view-rendered. Also the "dynamic" index-setting also doen't work since its view-rendered... But how can i achieve that when the button is clicked, it updates (ajax) the outputtext? Is this only possible with c:forEach?
its ViewScoped and the form must be outside of the loop. otherwise i would solve it with update="#form", but here its not possible
thanks for any help!

Since both ui:repeat and c:forEach generate different dynamic Component Ids for the elements you can't Guarantee the update an individual Item out of all generated items from outside.
I think best approach for this kind of problem would be placing a h:panelGroup around ui:repeat or c:forEach itself and update the h:panelGroupitself.

Related

p:ajax update of ID that doesn't exists

I'm using PrimeFaces and I have a line:
<p:ajax update="toUpdate">
the problem is, that this ID not always exists on the page.
( the page is dynamic and sometimes it contains a part that have this specific ID and sometimes not)
When it exists, it works great, but when the ID doesn't exist, the component crash - (probably it's some validation issue)
How can I fix it?
Is it a well known issue?
Thanks!
You need to provide an always rendered component to update, for example:
<p:ajax update="toUpdate">
<h:panelGroup id="toUpdate">
<p:dataTable id="tableID" rendered="#{bean.someCondition>"...
</h:panelGroup>
So, if you have a component that can be o or not visible, do not use it for update, because can be out of components tree. Instead, use a component (container) that your are sure that be rendered and present in the components tree.
Try this code
<f:ajax render="toUpdate">
<h:outputText id="toUpdate">
<!-- do something -->
</h:outputText>

ajax calls do not reRender when the page has nested ui:repeat [JSF1.2]

I have a page that have 2 ui:repeat to iterate a complex collection. I need add commandlinks that will update some of the data on the page without refresh the whole page. The code is like the following:
<h:panelGroup id="panel1">
#{backBean.getNumber()}
</h:panelGroup>
<h:form>
<a4j:commandlink action="#{backBean.increaseNumber()}" reRender="panel1" />
</h:form>
<ui:repeat value="#{masterlist}" var="list">
<ui:repeat value="#{list}" var="element">
#{element.description}
</ui:repeat>
</ui:repeat>
I can see the increaseNumber() method is called and the number is updated, but panel1 is not re-rendered. If I remove one ui:repeat tag and then it will work. I did research online and it seems there are issues with nested ui:repeat, but I couldn't find any solution.
I figured it out. Replace ui:repeat with a4j:repeat worked.

AJAX render attribute doesn't work with rendered="false" component [duplicate]

This question already has an answer here:
Ajax update/render does not work on a component which has rendered attribute
(1 answer)
Closed 6 years ago.
I have a component that I want to show/hide after user hits a commandButton.
It's like this:
<h:commandButton id="showButton" value="#{bean.wasPressed ? 'Hide' : 'Show'}">
<f:ajax listener="#{bean.toggle()}" render="explanation showButton" />
</h:commandButton>
and
<h:panelGroup id="explanation" rendered="#{bean.wasPressed}">
<h:outputText value="something" />
</h:panelGroup>
The bean.toggle() simply sets the wasPressed property to true or false appropriately. I am using <h:form prependId="false">.
The problem is the value of the render attribute of my button. It explicitly enlists both: explanation and showButton.
As long as the showButton is always present (it only changes its label), the explanation is present only if the wasPressed property is true. Otherwise it says:
malformedXML: During update: explanaition not found
How can I solve this problem?
I would like not to revert to hiding the element in the source code, so I would like not to use any jQuery toggle(-) or any way of hiding the element using style="display: none" or any of this stuff.
Is it even achievable in JSF 2.1?
You cannot update elements which are not rendered , rendered=false "is a JSF way to" to remove elements from the DOM Tree ,
its not like css display:none or visibility:hidden <- this two will keep the elements in the DOM tree but hidden , while the JSF rendered=false wont even render (keep) the element in the DOM tree (you wont even see it in the "view source" of the page)
So in you case you need to wrap the panelGroup with another `panelGroup' and update the id of the wrapper
<h:commandButton id="showButton" value="#{bean.wasPressed ? 'Hide' : 'Show'}">
<f:ajax listener="#{bean.toggle()}" render="explanationWrapper showButton" />
</h:commandButton>
<h:panelGroup id="explanationWrapper">
<h:panelGroup id="explanation" rendered="#{bean.wasPressed}">
<h:outputText value="something" />
</h:panelGroup>
</h:panelGroup>
also look at similar question
Can you update an h:outputLabel from a p:ajax listener?

Value to update attribute of primefaces command button

I have a query here regarding the value given to the update attribute of the primefaces command button.
Here is a simple code. I have a simple xhtml page
<h:body>
<h:form id="main">
<p:growl id="maingrowl" showDetail="true"></p:growl>
<p:panelGrid id="mainpanel" columns="2">
<p:commandButton value="Ajax Submit" update="test" id="ajax"
actionListener="#{mytestBean.display}" />
</p:panelGrid>
<p:panelGrid id="test" rendered="#{mytestBean.show}" columns="1">
<h:inputText value="#{mytestBean.val1}" />
<h:inputText value="#{mytestBean.val2}" />
<p:commandButton value="value in" id="aj" update="test"
actionListener="#{mytestBean.displaysec}">
</p:commandButton>
</p:panelGrid>
</h:form>
</h:body>
Now, If I have to update the panelgrid "test" then in the first command button I have to provide the id "test" prefixed with ":main:" in the update attribute of the command button since that is the exact id in the HTML DOM as I find it in the view source in the browser. But, I was able to update even by given just "test" in the update attribute.
So my question here is when should I use the ":" in the id or is it mandatory or is there any pre defined rule to give the id's in the attribute?
Also, I am aware of the fact that the id given in the update attribute is through the UINamingContainer in which it is placed. Please pardon me if its trivial, I am really confused here.
Any help greatly appreciated.
Thank you.
If both components (the one to update and the one that triggers the update) are inside the same NamingContainer, the relative client id withoud the : is sufficient.
NamingContainers in jsf are all those components that prepend their own id to the client id of all child components, e.g. <h:form>, <h:dataTable> or <ui:repeat> (or to be more precise: all components that implement the javax.faces.component.NamingContainer interface).
If both components are not inside the same NamingContainer, you have to use the absolute id beginning with a : from the view root.
If you are interested in more detailed information I recommend reading the javadoc of the UIComponent#findComponent() method where the search algorithm is described.
Note that the : is the default character to separate segments of a clientId. You can change it with a context parameter in your web.xml.

JSF: Execute values of multiple forms

I want to submit (execute) values from multiple forms, not just the enclosing form. So, I want to be able to do something like this:
<h:form id="form1>
<h:inputText id="testinput1" value="#{testBean.input1}" />
</h:form>
<h:form id="form2>
<h:inputText id="testinput2" value="#{testBean.input2}" />
<h:commandButton value="Submit">
<f:ajax execute=":form1 :form2"/>
</h:commandButton>
</h:form>
How would you solve this?
What is <f:ajax execute="#all"> really supposed to do? It POSTs only the enclosing form
seems to be related, but addresses a slightly different problem and also does not solve it (or this).
Ajax or not, this is not possible with plain JSF/HTML. All input elements which needs to be processed really needs to go inside the same form.

Resources