Ajax-render a table which is inside a different form - ajax

I am facing a problem rendering a data table when selecting a date from <rich:calendar>. I use <a4j:ajax> for the rendering but with no effect. Here is the code sample:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:composite="http://java.sun.com/jsf/composite">
<rich:panel header="#{lang.reportPanelHeader}" id="panel" rendered="#{navigation.reportRendered}" width="700px" style="margin-left:250px">
<a4j:status onstart="#{rich:component('statPane')}.show()" onstop="#{rich:component('statPane')}.hide()" />
<h:form id="data_table_form">
<rich:dataTable value="#{validateReportAction.reportList}" var="report" iterationStatusVar="it" id="data_table" rows="5">
<rich:column>
<f:facet name="header">#</f:facet>
#{it.index + 1}
</rich:column>
<rich:column>
....
</rich:column>
<f:facet name="footer">
<rich:dataScroller page="#{validateReportAction.page}" />
</f:facet>
</rich:dataTable>
</h:form>
<rich:popupPanel id="statPane" autosized="true" style="border: none; background-color: #e6e6e6;">
....
</rich:popupPanel>
<div id="bottom">
<h:form id="calendarForm">
<div id="left">
<div class="input" id="test_cal">
<rich:calendar
dataModel="#{calendarModel}"
value="#{validateReportAction.selectedDate}"
boundaryDatesMode="scroll"
required="true"
requiredMessage="#{lang.dateRequiredMsg}"
mode="ajax"
id="date"
datePattern="dd.MM.yyyy"
popup="false">
<a4j:ajax event="change" render="#all"/>
</rich:calendar>
<span class="error_msg">
<rich:message for="date" ajaxRendered="true"/>
</span>
</div>
</div>
</h:form>
</div>
</rich:panel>
</ui:composition>
I am forced to use #all in the calendar in <a4j:ajax event="change" render="#all"/> but I want to render only the data table. How can I do this?

Since it's located in a different naming container parent, you need to refer it by its absolute client ID. To find it out, open the page in the webbrowser. Rightclick and View Source. Locate the HTML <table> element which is generated by <rich:dataTable id="data_table">. It'll look something like this:
<table id="data_table_form:data_table">
You need to take exactly that ID, prefix with the JSF naming container separator character (which defaults to :) and use it in the render attribute.
<a4j:ajax event="change" render=":data_table_form:data_table" />
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"

Related

jsf ajax rendered does not work

I would like to ask why partial rendering for primefaces does not work. POST requests are keeping sent, but it does not rerender.
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<p:messages />
<h:form>
<table style="width: 100%">
<tr>
<td><p:outputLabel for="inp1" value="S1" /></td>
<td>
<p:inputText id="inp1" value="#{form.e.s1}">
<p:ajax process="inp1" update="msg1"
event="keyup" />
</p:inputText>
<p:watermark for="inp1" value="Wpisz S1" />
<p:message for="inp1" id="msg1" />
</td>
</tr>
<tr>
<td>Toolbox</td>
<td>
<p:selectBooleanCheckbox id="inpToolbox" value="#{form.toolbox}">
<p:ajax process="inpToolbox" update="toolboxOptions" />
</p:selectBooleanCheckbox><br />
<p:panel id="toolboxOptions" rendered="#{form.toolbox}">
Name: <p:inputText value="#{form.toolboxDescription}" /><br />
Number: <p:inputText value="#{form.toolboxNr}" /><br />
</p:panel>
</td>
</tr>
</table>
<p:commandButton action="#{form.save}" ajax="false"
value="Save" />
</h:form>
</h:body>
</html>
I have no idea, why it should not work. I want every time changes the toolbox value to show the additional information form about toolbox
When you would like to update some part of the view you have to specify an id of an element which is actually present in the DOM. But the panel you are trying to update is not always present in the DOM, only in the case that form.toolbox evaluates to true. So when it is false it cant be updated and so it will not be added to the view.
What you can do to solve this problem is, to wrap the panel inside another element and update that element. This will work because the wrapper-element is always present.
So try the following for the part of the panel:
<h:panelGroup id="toolboxOptions">
<p:panel id="toolboxOptionsPanel" rendered="#{form.toolbox}">
....
</p:panel>
</h:panelGroup>
Have a look at to answer of the following question for further explanation:
JSF + PrimeFaces: `update` attribute does not update component

<f:ajax> contains an unknown id when switching from PrimeFaces to jsf/html

this is my 1st question here :)
My code is as follows:
<?xml version="1.0"?>
<f:view xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
>
<h:head />
<h:body>
<h:form id="filterForm">
<h:outputStylesheet library="css" name="main.css" />
<div id="filterPane">
<h:panelGroup rendered="#{not empty filters.categories}">
<div class="filter">
<div class="filterCategories" style="width: 100%;">
<h4>Kategorien</h4>
<p />
<h:selectManyCheckbox layout="pageDirection"
value="#{filters.selectedCategories}"
valueChangeListener="#{filters.categoryValueChanged}">
<f:selectItems value="#{filters.categories}" var="category"
itemLabel="#{category.displayName} (#{category.count})"
itemValue="#{category.name}" />
<f:ajax render="#form" />
</h:selectManyCheckbox>
</div>
</div>
</h:panelGroup>
</div>
</h:form>
</h:body>
</f:view>
I get the same error as some others before me here #stackoverflow - but none of the suggested solutions worked for me.:
<f:ajax> contains an unknown id 'A5539:filterForm:j_idt9' - cannot locate it in the context of the component j_idt9
Before my switch from <p:selectManyCheckbox to <h:selectManyCheckbox the code was working fine.
We need to change to <h:selectedManyCheckbox, because the PrimeFaces variant is not selectable for a non-JavaScript user. I need the form <h:form id="filterForm"> to be re-rendered as a consequence of my AJaX request via the <f:ajax> element.
Beside the initial <f:ajax render="#form" /> I unsuccessfully tried to reference the <h:form id="filterForm"> element with the following variants:
<f:ajax render=":filterForm" />
<f:ajax render=":#{component.parent.parent}" />
I also tried some more stupid ones.
Any hint, anybody!? :)

Update component with Ajax results in Exception

It seems like I am simply unable to grasp, how updating components with Ajax works. I keep on getting an Exception "Cannot find component with identifier ":menu-item-container" referenced from "j_idt12:0:j_idt16:j_idt76"."
This is my code:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<f:view contentType="text/html">
<h:head>
<title><ui:insert name="pageTitle"></ui:insert></title>
</h:head>
<h:body>
<h:outputStylesheet library="css" name="style.css" />
<div class="menu-navigation">
<ul>
<li>Menu</li>
<ui:repeat var="category"
value="#{restaurantsBean.restaurant.categories}">
<h:form>
<li><p:commandLink update=":menu-item-container">
<div>
#{category.name}
<f:setPropertyActionListener value="#{category.id}"
target="# {restaurantMenuBean.selected}" />
</div>
</p:commandLink></li>
</h:form>
</ui:repeat>
</ul>
</div>
<div id="menu-item-container">
<ui:repeat var="category"
value="#{restaurantsBean.restaurant.categories}">
<p:outputPanel>
<h:panelGroup id="pangroup" layout="block"
rendered="#{restaurantMenuBean.active(category.id)}">
<div class="some-heading">
<h2>#{category.name}</h2>
</div>
<div class="category-description">#{category.description}</div>
<ui:repeat var="item" value="#{category.items}">
<p:outputPanel
rendered="#{restaurantMenuBean.needLightbox(item)}">
<ui:include src="/lightbox-item.xhtml"></ui:include>
</p:outputPanel>
<p:outputPanel
rendered="#{!restaurantMenuBean.needLightbox(item)}">
<ui:include src="/nolightbox-item.xhtml"></ui:include>
</p:outputPanel>
</ui:repeat>
</h:panelGroup>
</p:outputPanel>
</ui:repeat>
</div>
</h:body>
</f:view>
</html>
This is the related area of html source output, which tells me, my "menu-item-container" is right at the root and the update-attribute only needs a separation marker ":" in front of its id.
<div id="menu-item-container"><span id="j_idt17:0:j_idt64"></span><span id="j_idt17:1:j_idt64"><div id="j_idt17:1:pangroup">
<div class="some-heading">
The to-be-updated components are resolved using the algorithm as described in UIViewRoot#findComponent(). It should be obvious that it can find fullworthy JSF components only.
Your menu-item-container is however a plain HTML <div> element and thus unavailable in the JSF component tree.
Replace it by a fullworthy JSF component.
<h:panelGroup id="menu-item-container" layout="block">
The <h:panelGroup> renders by default a <span> and the layout="block" turns it into a <div>.

Updating dataTable data after clicking on Search button

Once page xyz.xhtml gets loaded, I am displaying 10 records.
<h:dataTable var="c" value="#{userServiceBean.showTop10Applicant()}"
styleClass="order-table"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row"
border="1" id="appListDataTable" width="100%">
<h:column>
<f:facet name="header">
Applicant Name
</f:facet>
#{c.displayName}
</h:column>
</dataTable>
In showTop10Applicant() I'm returning 10 random records.
Above this dataTable, I have search textbox and search button. I have used ajax for checking the data.
<h:inputText id="searchApplicant" value="#{userDataBean.toSearch}" /> +
<h:commandButton value="Search" action="#{userServiceBean.searchApplicantsByCriteria()}">
<f:ajax execute="searchApplicant" render=":appListDataTable"/>
</h:commandButton>
In searchApplicantsByCriteria() I am displaying all records that I have (right now I am not checking for any criteria).
BUT, when I click on Search, I get same 10 records back as earlier.
Could anyone help where I am getting wrong.
Update 1
Below is what I want to do.
I want to search some persons that are there in database. When the page gets loaded, I am displaying random 10 persons using dataTable (using method showTop10Applicant()).
In Search textbox, I write abc and click on Search button. What I want is that the dataTable that is already present (where we are displaying 10 random records) get updated with the finding of abc. Lets say there are 2 person whose name contains abc, then I should get only list of these two persons.
Hope I am clear now. Let me know incase if there are any questions.
Update 2
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:body>
<ui:composition template="../layout/homeLayout.xhtml">
<ui:define name="content">
<center>
<h2>
<u>
<h:outputText value="Manage Applicants"></h:outputText>
</u>
</h2>
</center>
<br />
<h:form id="myForm002" prependId="false">
<div align="right">
<h:inputText id="searchApplicant" value="#{userDataBean.toSearch}" /> +
<h:selectOneMenu value="#{userDataBean.status}">
<f:selectItem itemValue="ALL" itemLabel="All" />
<f:selectItem itemValue="A" itemLabel="Active" />
<f:selectItem itemValue="IA" itemLabel="Inactive" />
</h:selectOneMenu>
<h:commandButton value="Search" action="#{userServiceBean.searchApplicantsByCriteria()}">
<f:ajax execute="searchApplicant" render=":myForm001:appListDataTable"/>
</h:commandButton>
</div>
</h:form>
<hr width="100%"></hr>
<br />
<center>
<h:form id="myForm001" prependId="false">
<f:metadata>
<f:event listener="#{userServiceBean.showTop10Applicant()}" type="preRenderView" />
</f:metadata>
<h:dataTable var="c" value="#{userServiceBean.showTop10Applicant()}"
styleClass="order-table"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row"
border="1" id="appListDataTable" width="100%">
<h:column>
<f:facet name="header">
Applicant Name
</f:facet>
#{c.displayName}
</h:column>
<h:column>
<f:facet name="header">
User ID
</f:facet>
#{c.userId}
</h:column>
<h:column>
<f:facet name="header">
Email ID
</f:facet>
#{c.email}
</h:column>
<h:column>
<f:facet name="header">
Mobile Number
</f:facet>
#{c.contactReference}
</h:column>
<h:column>
<f:facet name="header">
Active?
</f:facet>
<h:selectBooleanCheckbox value="#{c.isActive}"></h:selectBooleanCheckbox>
</h:column>
</h:dataTable>
<br />
</h:form>
</center>
</ui:define>
</ui:composition>
</h:body>
</html>
You need to wrap the datatable in a panelGroup like <h:panelGroup id="dataTableGroup"> and then call <f:ajax execute="searchApplicant" render="dataTableGroup"/>. This should work.
You are updating the wrong component. The ":" is the document root and you certainly have a form tag wrapped around your dataTable (that's why I asked for the form). So at least you should use something like this:
render=":formId:appListDataTable"
Replace formId with your real form id. This assumes that there are no other naming containers in between like h:panelGroup etc.
If both (the input field and the table) are inside the same naming container you could omit the colon:
render="appListDataTable"
Furthermore there might be other sources of error. I would suspect your backing bean methods (as commented by Daniel, that's why I asked for the bean code).

rich:tabPanel and problems when field has required="true"

Let's consider following, simplified example:
We have 2 tabs withing <rich:tabPanel switchType="ajax">, each tab has <h:inputText value="" required="true" /> and at the moment we want to switch from one tab to another, and the inputText is empty (we don't want to submit value from it anyway, we want to go to another tab) we get "Validation Error: Value is required."
The example code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
>
<a4j:form id="mainForm"
reRender="mainForm"
ajaxSubmit="true">
<rich:tabPanel switchType="ajax">
<rich:tab label="TabA" >
<a4j:region>
<h:outputText value="Tab A content" />
<h:inputText value="" required="true" />
</a4j:region>
</rich:tab>
<rich:tab label="TabB">
<a4j:region>
<h:outputText value="Tab B content" />
<h:inputText value="" required="true" />
</a4j:region>
</rich:tab>
</rich:tabPanel>
<rich:messages />
</a4j:form>
</html>
You should add the "immediate" attribute to the tabPanel. To quote the docs this means that the tabPanel:
"...component value must be converted and
validated immediately (that is, during
Apply Request Values phase), rather
than waiting until a Process
Validations phase"
For example:
<rich:tabPanel switchType="ajax" immediate="true">

Resources