How to render a component outside datatable by ajax? - ajax

I have a <h:dataTable> with a <h:commandLink> in a column and a <h:outputext> outside the <h:dataTable> which I need to render by the command link.
<h:form>
<h:dataTable value="#{userControl.lista}" var="c">
<h:column>
<f:facet name="header" >
<h:outputText styleClass="leftColumn" value="Nombre"/>
</f:facet>
#{c.nombre}
</h:column>
<h:column>
<f:facet name="header" >
Usuario
</f:facet>
<h:commandLink actionListener="#{userControl.setAdmin_user(c.user)}" value="#{c.user}">
<f:ajax render="output" />
</h:commandLink>
</h:column>
</h:dataTable>
<h:outputText id="output" value="#{userControl.admin_user}"/>
</h:form>
It does not work. If I move the <h:outputText> inside the same column, then it works.
How is this caused and how can I solve it?

The client ID as you currently have in the <f:ajax render> does not start with the default NamingContainer separator character : and is therefore relative to the current NamingContainer component, which is in your case the <h:dataTable>. So it will work only when the outputtext component is also in the same datatable.
You need to refer the outputtext component by an absolute client ID instead. For starters who do not have memorized all NamingContainer components yet, the easiest way to find it out is to check the id attribute of the generated HTML element in the webbrowser. Open the page in webbrowser and do View Source and locate the <span> element generated by <h:outputText id="output"> and take exactly this ID and prefix it with : to make it absolute to the view root.
E.g.
<span id="formId:output">
where formId is the ID of any <h:form> for the case the outputtext is enclosed in a <h:form>. If you don't have specified a fixed ID for the <h:form>, then JSF will autogenerate one. You'd like to specify a fixed ID then like <h:form id="formId">.
So the <f:ajax render> should look like this then
<f:ajax render=":formId:output" />

Related

Rendering datatable column with ajax and jsf

I have a datatable listing some items with several details :
<h:dataTable id="versionInterfaces_datatable"
styleClass="datatable" rowClasses="odd,even"
value="#{versionToolManager.version.interfaces}"
var="lInterface">
<h:column>
<f:facet name="header">Interface Name</f:facet>
<h:commandLink id="versionInterfacesName_columnLink"
value="#{lInterface.name}"
action="#{interfaceManager.consult}">
<f:setPropertyActionListener
target="#{interfaceManager.interfaceEntity}"
value="#{lInterface}" />
</h:commandLink>
<h:outputText id="versionInterfacesName_column" value="#{lInterface.name}" />
</h:column>
<h:column id="interfaceVersions_column">
<f:facet name="header">Interface Version(s)</f:facet>
<ui:repeat value="#{lInterface.versionsInterface}" var="lVersionI"
varStatus="lStatus">
<h:outputText rendered="#{lVersionI.versionsTools.contains(versionToolManager.version)}" value=" #{lVersionI.name} | " />
</ui:repeat>
</h:column>
<h:column>
<f:facet name="header">Interface Description</f:facet>
<h:outputText id="versionInterfacesDescription_column"
value="#{lInterface.description}" />
</h:column>
and then I have a button calling a modal view allowing to add items :
<h:commandButton id="#{id}OpenModal_button"
value="#{openButtonValue}"
onclick="document.getElementById('#{formId}:#{modal_panel}').style.display='block'; return false;" />
<br />
when closing this modal view, I try to "refresh" the datatable to see the items added :
<h:commandButton id="#{id}CloseModal_button"
value="#{closeButtonValue}">
<f:ajax execute="#this"
render="#{renderOnClose} #{formId}:#{modal_panel}" />
</h:commandButton>
But the columns of my datatable are not all updated, the column "Interface Version(s)" is empty for the new lines corresponding to the new items even though when I save, they have been well added.
Do you have any idea ?
the problem is <f:ajax execute="#this" ...
use <f:ajax execute="#all" ...
So I succeed to solve my problem but it wasn't a problem about the syntax but a bad use of the model and beans structure. Without going into details, I was trying to reach data which weren't linked to the corresponding items.

Datatable not rendering with ajax call in jsf

I have a data table that needs to be refreshed upon using an ajax command found in each row.
<div class="authorSection">
<h:dataTable id="author-table" var="author" value="#{authorPOCBean.getauthors()}">
<h:column>
<f:facet name="header">
<h:outputText value="Org Short Name" />
</f:facet>
<h:outputText id="authorOrganizationShortName" value="#author.orgShortName}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Organization Name" />
</f:facet>
<h:outputText id="authorOrganizationName" value="#{author.orgName}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Location" />
</f:facet>
<h:outputText id="authorLocation" value="#{author.orgLocation}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="author Type" />
</f:facet>
<h:outputText id="authorType" value="#{author.authorName}" />
</h:column>
<h:column>
<h:form id="deleteauthorForm">
<h:commandLink action="#{authorPOCBean.deleteauthor(author)}" value="Delete">
<f:ajax render=":author-table"/>
</h:commandLink>
</h:form>
<h:form id="setInitialauthorForm">
<h:commandLink action="#{authorPOCBean.makeInitialauthor(author)}" value="Make Initial"/>
</h:form>
</h:column>
</h:dataTable>
</div>
When the delete function is used it seems to leave the table unchanged or perhaps renders it with old data? I've got it set now to the first thing the called method does is change the internal array THEN changes the database stuff but it still uses the old data.
Is there something obviously wrong with my code?
I have looked at the below link and tried the recommendations and have no new result. In fact if I surround the table with a form the table won't build right.
JSF- <f:ajax> can't render datatable
Please be noted that you have placed the Delete Button and Make initial Buttons enclosed in a separate form whereas the DataTable component is placed outside the form .
Try having a single form starting at at the start of the table . (ie) Your table component and the two buttons should be enclosed within the same form
and for Ajaxical refresh, the following should work for you .
<f:ajax render="#form"/>
If for some other reason you cannot use a single form and need multiple forms , Please refer this question How to retain form data in a multi form page

Ajax jsf 2 sort datatable based on select list item selection (on button click)

So I want to ajax up a data table to change and be filtered based on which state is selected in the drop down. I have the following:
<p>Choose State to Filter By:</p>
<h:selectOneMenu value="#{productListingBean.choosenState}">
<f:selectItem itemValue="All" />
<f:selectItems value="#{productListingBean.stateList}" />
</h:selectOneMenu>
<h:commandButton value="Sort">
<f:ajax event="action" render="myTable" />
</h:commandButton>
and
<h:dataTable id="myTable" value="#{productListingBean.getAllProducts()}" var="product" styleClass="hovertable">
<h:column>
<f:facet name="header">
ID
</f:facet> ...
my product bean is request scoped and I save the selection from the selectOnmenu in the Choosen state variable and getAllProducts() method handles the filtering.
What am I missing, this does not work?
The issues seems to be that this needs to be surrounded in a tag.

How to pass an iterated parameter via ajax to a backing bean method

So, I have a dataTable that looks like this:
<h:form>
<h:dataTable value="#{backingBean.employeeLineItems}" var="emp">
<h:column>
<f:facet name="header">First</f:facet>
#{emp.lastname}
</h:column>
<h:column>
<f:facet name="header">Last</f:facet>
#{emp.firstname}
</h:column>
<h:column>
<f:facet name="header">Actions</f:facet>
<h:commandButton value="View Details">
<f:ajax execute="#{setCurrentEmployeeId(emp.id)}" render="employeeDetails"/>
</h:commandButton>
</h:column>
</h:dataTable>
<h:outputText value="#{backingBean.employeeDetails}" id="employeeDetails"/>
</h:form>
For each row of the datatable, there is a button that I want to, when clicked, ajax the employeeLineItem id value over to a method that sets that id in the backing bean, and then renders the outputText tag with id "employeeDetails" (The getEmployeeDetails method would use the employeeLineItem id to get the right employee details object from the database, of course)
My solution doesn't seem to be working, does anyone know what I'm doing wrong?
<h:commandButton value="View Details">
<f:ajax execute="#{setCurrentEmployeeId(emp.id)}" render="employeeDetails"/>
</h:commandButton>
This is wrong. The execute attribute of <f:ajax> should point to a space separated collection of component client IDs which are to be submitted and processed in the server side (the same way as you specify the render attribute with a space separated collection of component client IDs which are to be updated/re-rendered after the ajax request). In your particular case, it should have been the ID of the datatable or the form, or just #form to generically refer the parent form.
The action method wherein you pass the row ID should be definied in the action attribute of the <h:commandButton> instead. So, this should do:
<h:commandButton value="View Details" action="#{backingBean.setCurrentEmployeeId(emp.id)}">
<f:ajax execute="#form" render="employeeDetails"/>
</h:commandButton>
(note that I fixed the missing managed bean name in the action method)
By the way, are you aware that you can also just pass whole objects along as arguments in EL?
<h:commandButton value="View Details" action="#{backingBean.setCurrentEmployee(emp)}">
<f:ajax execute="#form" render="employeeDetails"/>
</h:commandButton>
This way you don't need to reload the employee from the DB.

Component ID in ui:repeat problems

I'm trying to render a grandparent component.
The code:
<h:form prependId="false>
<h:panelGroup id="outer_panel">
<ui:repeat var="curr" value="#{bean.map}">
<h:panelGroup id="inner_panel">
<h:commandButton value="Remove" action="actionThing" >
<f:ajax render="outer_panel" />
</h:commandButton>
</h:panelGroup>
</ui:repeat>
</h:panelGroup>
</h:form>
I get an exception:
javax.faces.FacesException: Component with id:outer_panel not found
Tried to add the index to the id, which didn't work neither:
<h:form prependId="false>
<h:panelGroup id="outer_panel">
<ui:repeat var="curr" value="#{bean.map}" varStatus="loop">
<h:panelGroup id="inner_panel">
<h:commandButton value="Remove" action="actionThing" >
<f:ajax render="#{loop.index+1}:outer_panel" />
</h:commandButton>
</h:panelGroup>
</ui:repeat>
</h:panelGroup>
</h:form>
Any idea why the ID is not found?
Thanks.
It is not found because you used a relative client ID in render attribute. It becomes relative to the closest parent naming container component. In this case, that's the <ui:repeat> (it prepends generated client ID of the children with the row index). So the component with ID outer_panel has to be inside the <ui:repeat> in order to get it to work. However, the outer_panel is actually outside it.
You need to specify an absolute client ID instead of a relative client ID. To make it absolute (so that it will basically scan from the view root on), prefix the client ID with :.
<f:ajax render=":outer_panel" />
For the case that you didn't use prependId="false" on the <h:form>, then you should have used
<f:ajax render=":form_id:outer_panel" />
instead.

Resources