jsf2 f:ajax render issue in datatable - ajax

I have a datatable and for each line have a delete linkcommand, as following:
<h:dataTable value='#{glbProjectDtoList}' var='projectDto'
binding='#{projectController.projectDataTable}' styleClass='display'
id='tblProject' rowClasses='gradeA, gradeA'
columnClasses='projectTableName, projectTableProgress, projectTableAction'>
......
<h:commandLink
action="#{projectController.delete(projectDto.projectId)}">
<img class="btnDeleteProject mr5"
src="#{request.contextPath}/resources/images/icons/dark/trash.png" />
<f:ajax execute="#form"
onevent="function(data) {deleteProjectEventHandler(data);}"
render=":tblProject" />
</h:commandLink>
......
</h:dataTable>
The delete function works fine, but the whole datatable is not reRendered, is it because the action nested in data table or by some other reason?
Update :
It's not working, after remove (:), throw following exception:
javax.faces.FacesException: <f:ajax> contains an unknown id 'tblProject' - cannot locate it in the context of the component j_idt68
means without (:), the element must be in same h:form tag.
Thanks in advance.
-Cow

Remove the : in front of the id:
<f:ajax execute="#form" onevent="function(data) {deleteProjectEventHandler(data);}" render="tblProject"/>
If the id starts with a separator character (usually :) the component is searched from the root component, otherwise it is searched from the next NamingContainer.
Have a look at the javadoc for more information: UIComponent.findComponent

This is possibly happening because the id of the datatable is not found in the viewroot when component state is getting refreshed.
To find out the exact ID by which this component is present on the
viewroot, please check the page source and find out the ID by which
this datatable is rendered.
You need to use the same ID as those found in the viewSource to allow the component to be visible in viewRoot when the state is changed.
Alternatively, UIComponent.findComponent will also help and if ID you are specifying is correct it will return you the UIComponent instance else it will return null.

I have go another approach, use hiding form outside of the table. It works.
Thanks everyone ;)

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>

Primefaces p:selectOneMenu or p:selectBooleanCheckbox not firing change-event depending on if I use h:form

I'm working with Primefaces 5.3.
First, I implemented functionality to change visibility of a p:selectOneMenu depending on the value of a p:selectBooleanCheckbox according to this post:
Enabling and disabling components via select checkbox
This works so far, if I use the h:form.
Next, I wanted to update the values in the bean, as chosen in the p:selectOneMenu. This is where my question starts: Even if i use p:ajax to explicitly call a listener, it won't get called. This is my code:
<h:panelGrid>
<p:selectOneMenu value="#{schedulerCDIBean.selectedParentTask}" var="parentTask" id="taskDependence" disabled="#{task.dependsOn != 'true'}">
<p:ajax event="change" listener="#{schedulerCDIBean.taskToAddListener}"/>
<f:selectItems id="taskDependenceItems" value="#{schedulerCDIBean.taskWebDataObjectList}" var="item" itemLabel="#{item.taskName}"
itemValue="#{item}" />
<p:column>
<h:outputText value="#{parentTask}"/>
</p:column>
</p:selectOneMenu>
</h:panelGrid>
And here is how I enable/disable the selectOneMenu:
<p:selectBooleanCheckbox id="dependsOnTask" value="#{task.dependsOn}" itemLabel="Depends On">
<p:ajax update="taskDependence" process="#this"/>
</p:selectBooleanCheckbox>
All this lives inside a p:tab of the p:accordionPanel where 'task' is the var of my DataObject-List.
As mentioned by #BalusC in this post: commandLink/commandButton/ajax backing bean action/listener method not invoked (Possible Causes: 2),
"You cannot nest multiple UIForm components in each other."
So, if i remove the h:form directive, the call to the listener in the bean works. But now, the value of the p:selectBooleanCheckbox is always set to 'false', and thus the component is not being updated to visible.
I found a post here, where OP had the same problem and solved it by adding the h:form directive.
EDIT:
My 'form' is a ui:composition and starts like this <ui:composition template="/templates/pages/mainPage.xhtml">, where mainPage.xhtml contains h:head and includes the 'header.xhtml' by using ui:include, and there is a h:form. But this h:form is already closed before, so the problem isn't here.
Well, I don't want to go the way with adding the h:form again, as it leads to unspecified behaviour. But what am I doing wrong, if my p:selectBooleanCheckbox values are not being set correctly?
Thank you for your help!
UPDATE
The problem was not the h:form, as it actually wasn't nested. Now I'm just still stuck with the listeners for the p:selectOneMenu, as they aren't being called. I also tried setting partialSubmit="true" on the <p:ajax />, which did not lead to a solution so far.
Thanks for your help, guys. With your help I fixed the problem.
Just as if someone else experiences similar problems, here a few things to check:
Check #BalusC's answer here, as also mentioned in #irieill's answer.
Check if you're having equals() and hashCode() of the object you're willing to show in the selectOneMenu.
The solution for my situation actually was mentioned in #irieill's comment:
[..]Not providing a proper converter does not raise any exceptions but faces error messages. So try to add a <p:growl autoUpdate="true" /> to your page to see if any conversion error is raised. If so, add a propper converter to your selectOneMenu.
I think, that's also what #BalusC said at point 3 of his list of possible causes.
See also: How to write a custom converter for <p:pickList>, Custom converter in JSF 2.0, PrimeFaces ShowCase: SelectOneMenu
As mentioned by #BalusC in this post: commandLink/commandButton/ajax backing bean action/listener method not invoked
Also note point 1. You must enclose your input components with a <h:form /> tag.
Well, I don't want to go the way with adding the h:form again, as it leads to unspecified behaviour.
As i understand, you are misusing the tag or you do not understand how to use it. Just enclose your whole page (or at least all input components) in one <h:form /> tag and it should work.
Can you please update your question with the page code also containing the lines where you placed the <h:form /> tag(s).

How to reRender an inputText generated dynamically by a dataTable using Ajax

I'm using here in my project JSF 1.2 and the Tag <a4j:support> .
Well, i'm using here a <h:dataTable /> to print on the screen a list of financial expenses, where it's possible for the user to insert new expenses or edit the existed expenses at anytime, the value of these expenses fields (amount, balance, value) are being shown in inputTexts components.
As i'm using a <h:dataTable /> the inputTexts of it are generated automatically, so it creates dynamical inputTexts with dynamical ids. I took a look at the html source code of the page and the pattern JSF uses to generate the ids in a dynamically way is this:
id="formTemplate:tableForm:0:inputTextValue" ;
id="formTemplate:tableForm:1:inputTextValue" ;
id="formTemplate:tableForm:2:inputTextValue"
And in the xhtml page the code i used with the dataTable is this:
<h:inputText id="inputTextValue" value="#{item.value}" label="Value" styleClass="field" size="9" readonly="true" dir="RTL" style="font-size:12px;width:170px">
My business rule works like that: When the user types something in the inputTextBalance it calls the event onBlur where it automatically inserts an other value in the field "value", but to update this inputTextValue i need to do a reRender in my panel (panelDataTable), so it reRender the whole dataTable (dataTable is inside the Panel).
<h:inputText id="inputTextBalance" value="#{item.balance}" dir="RTL">
<f:convertNumber currencyCode="BRL" type="currency" />
<a4j:support event="onblur" reRender="panelDataTable" ajaxSingle="true" action="#{expenses.update}"/>
</h:inputText>
Now comes the trouble, what i need to do is to reRender only the inputTextValue instead of the panel, but these fields are generated dynamically and i can't get there ids. Like i said before, this is the pattern that JSF uses to generate the id of the fields
id="formTemplate:tableForm:0:inputTextValue" ;
id="formTemplate:tableForm:1:inputTextValue" ;
id="formTemplate:tableForm:2:inputTextValue"
But when i use any of these ids in reRender attribute, the Ajax's log returns me this message:
18:23:57,208 WARN [AjaxContext] Target component for id formTemplate:tableForm:0:inputTextValue not found
I tried this but i got the same error message: reRender="#{rich:clientId('inputTextValue')}"
The weirdest thing here is that it shows me this message of the input not found, but in the html source code the id of he inputText is the same that i've puted to reRender.
Does anybody here have already delt with this problem? Any suggestions to me?
Thank you!
you should bind the h:dataTable to a variable in your bean, in order to reach the current row index.
<h:dataTable binding="#{myManagedBean.dataTable}" ...>
then you can change a4j:support like this:
<a4j:support reRender="formTemplate:tableForm:#{myManagedBean.dataTable.rowIndex}:inputTextValue" ... />

Rerendering composite component by ajax

I have build a composite component witch looks something like this:
<composite:interface>
<composite:attribute name="id" required="false" />
<composite:attribute name="label" required="true" />
</composite:interface>
<composite:implementation>
<h:panelGroup id="#{cc.attrs.id}">
<fieldset class="fieldset"><legend>${cc.attrs.label}</legend></fieldset>
</h:panelGroup>
</composite:implementation>
The compent displays the current label correctly.
<xyz:comp id="idMyComponent" label="#{someBean.text}"/>
...
<a4j:ajax ... render="idMyComponent" />
...
Now when the action is preformed nothing happens. However when I add a Postfix to the ID in the component it works fine (see below).
...
<composite:implementation>
<h:panelGroup id="#{cc.attrs.id}Label">
...
And define the ID in render with the postfix:
<xyz:comp id="idMyComponent" label="#{someBean.text}"/>
...
<a4j:ajax ... render="idMyComponentLabel" />
...
Can some on explain to me why it only works when I add a postfix to the ID in h:panelGroup?
This problem is actually two-fold.
The first problem is that the <xyz:comp id> actually specifies the ID of the composite component itself, the <cc:implementation>. This is by default nowhere represented in HTML output and therefore ajax/JavaScript can't locate it by document.getElementById() and friends.
Actually, your <h:panelGroup id="#{cc.attrs.id}"> ends up in generated HTML output as follows (rightclick page and View Source to see it yourself):
<span id="idMyComponent:idMyComponent">
The second "problem" is that RichFaces/Ajax4jsf has enhanced the referencing/finding of JSF components in the tree by relative client ID (i.e. not starting with :) by not only searching in the context of the current NamingContainer, but also in all other NamingContainer components. A composite component is inherently also a NamingContainer component.
Your first attempt failed because it found the composite itself instead of the panel group, but JS/ajax in turn failed to update because there doesn't exist any HTML element with id="myComponent" in the generated HTML output.
Your second attempt succeeded because it finally found the real panel group (note: because it also searched in all other NamingContainer components; this would still have failed if you've used <f:ajax> instead of <a4j:ajax>).
The right way to fix your problem is not using #{cc.attrs.id} on a JSF component, but using #{cc.clientId} on a plain HTML element.
<span id="#{cc.clientId}">
(yes, use a <span> or <div> instead of <h:panelGroup> inside the <cc:implementation>)
This way JSF can find the component by client ID (in order to generate the proper ajax response) and JS can find the HTML element by client ID (in order to update the right HTML element based on ajax response).
See also:
Is it possible to update non-JSF components (plain HTML) with JSF ajax?
Integrate JavaScript in JSF composite component, the clean way
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"

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.

Resources