jsf 2.0 f:ajax render ID not found - ajax

When the Save button in the popup(pp1) clicked the projects list gets updated.
But when press the update button in the projects list, the render ID :form1:pp1 is not there error comes when its being rendered. If do render="#all" it works, but its not good.
( error : <f:ajax> contains an unknown id ':form1:pp1')
<h:form id="form1" prependid=false>
<h:panelGroup id="projects">
<ui:repeat var="action" value="#{dadadada}" varStatus="status">
<h:commandButton value="Save">
//gives id not found error
<f:ajax event="click" execute="#form" render=":form1:pp1" listener="#{fsfsfsfsfs}" />
</h:commandButton>
</ui:repeat>
</h:panelGroup> // project panel group
//popup
<h:panelGroup id="pp1">
<div id="popup2" class="popup_block">
//save button in the popup
<div class="popupBody_save2">
<h:commandButton image="resources/images/saveBtn.gif" value="Save">
<f:ajax event="click" execute="#form" render="projects" listener="#{dfsfssfs}" />
</h:commandButton>
</div>
</div>
</h:panelGroup>
</h:form>

The :form1:pp1 won't work since you have prependId="false" on the form. The pp1 won't work since it's then looking for the component in the same scope as <ui:repeat> which is by itself an UINamingContainer component.
Open the JSF page in webbrowser, rightclick and View Source to get the generated HTML. Locate the HTML element which is generated by <h:panelGroup id="pp1">. It should look something like this
<span id="foo:bar:pp1">
You need to use exactly this ID prefixed with : in the render attribute.
<f:ajax render=":foo:bar:pp1">
If there's an autogenerated ID part such as j_id0, then you need to give the parent component in question an fixed ID.

If you use prependId=false your panelGroup's id is pp1 instead of form1:pp1. (Assume there is a typo in your attribute "prependID" instead of "prependid")

Related

JSF and AJAX: hiding part of site until first ajax request

I'm trying to create a page where some content will be displayed after ajax request. Here is part of my code:
<h:panelGroup>
<h:form>
Retrive object by id: <h:inputText id="myInput" value="#{myManager.id}"/>
<h:commandButton value="ok" action="#{myManager.getById}" >
<f:ajax execute="myInput" render="resultRow" />
</h:commandButton>
<h:panelGroup id="resultRow" >
<br />
You retrived object which id is:
<h:outputText value="#{retrivedObject.id}" />
and its name is:
<h:outputText value="#{retrivedObject.name}" />
</h:panelGroup>
</h:form>
</h:panelGroup>
My problem is taht the "You retrived object which id is: " is rendered even before I retrive any object. I want it to be hidden until I click my command button. Is it possible to do only with jsf + html (this have to be done with ajax)? I could use some javascript if I will have to, but I prefer not.
I tried to solve this by rendered="#{!retrivedObject.id==0}" (my object can't have id 0), but this doesn't work - panel group isn't rendered at all and when I call ajax reqest it is unable to find "resultRow" id.
Thanks for help in advance.
It may not be exactly what you are looking for but you can always wrap the panelGroup in a div and set the div visibility to hidden, then use javascript to change the visibility when you click the command button.
You can use the rendered attribute like this :
<h:panelGroup>
<h:form>
Retrive object by id: <h:inputText id="myInput" value="#{myManager.id}"/>
<h:commandButton value="ok" action="#{myManager.getById}" >
<f:ajax execute="myInput" render="resultRow" />
</h:commandButton>
<h:panelGroup id="resultRow">
<h:panelGroup rendered="#{retrivedObject ne null}">
<br />
You retrived object which id is:
<h:outputText value="#{retrivedObject.id}" />
and its name is:
<h:outputText value="#{retrivedObject.name}" />
</h:panelGroup>
</h:panelGroup>
</h:form>
</h:panelGroup>

Render ids generated by nested <f:ajax> inside <ui:repeat> do not match those generated by JSF

My form contains a dropdown list inside a ui:repeat component. When any list item is selected, an f:ajax call triggers a refresh of both dropdown list and several other components inside ui:repeat . Im struggling to work out the correct id format for the f:ajax render="???????" (see facelet view below). Any help would be appreciated.
Ive supplied raw source view of the rendered screen (actual JSF ids) and a facelet view showing the same components as coded.
Browser Source View
<form id="GeneralMedicalHistory" name="GeneralMedicalHistory" method="post" action="..."
<span id="GeneralMedicalHistory:GeneralMedicalHistory_P">
<span id="GeneralMedicalHistory:medhist">
<table border="0" class="table_form">
<select id="GeneralMedicalHistory:RPTK:0:MedicalCondition" name="GeneralMedicalHistory:RPTK:0:MedicalCondition" > ---> TARGET ID (UI:REPEAT)
Facelet view
<h:form id ="GeneralMedicalHistory">
<h:panelGroup id="GeneralMedicalHistory_P">
<h:panelGroup id="medhist">
<ui:repeat value="#{f.repeatingItemGroups['MedicalHistory'][1]}" var="repeatKey" id="RPTK" >
<h:commandLink action="remove_repeating_ig" rendered="${f.items[removeOid].isNew and repeatKey != '1'}"></>
<table border="0" class="table_form">
<h:selectOneMenu value="${f.items[oid].value}" id="MedicalCondition" >
<f:selectItems value="${f.items[oid].codeListItems}"/>
<f:ajax render="?????????" event="click" listener="#{f.clearModelValuesViaAjax}" />
</h:selectOneMenu>
</table>
</h:panelGroup>
</h:panelGroup>
</h:form>
Ive tried the following but none have worked...
f:ajax render="GeneralMedicalHistory:RPTK:0:MedicalCondition"
f:ajax render=":GeneralMedicalHistory:RPTK:0:MedicalCondition"
f:ajax render="GeneralMedicalHistory_P:medhist:RPTK:0:MedicalCondition"
f:ajax render=":GeneralMedicalHistory_P:medhist:RPTK:0:MedicalCondition"
f:ajax render="GeneralMedicalHistory:GeneralMedicalHistory_P:medhist:RPTK:0:MedicalCondition"
f:ajax render=":GeneralMedicalHistory:GeneralMedicalHistory_P:medhist:RPTK:0:MedicalCondition"
The <ui:repeat> is by itself a NamingContainer. You can just reference a client ID relative to the <ui:repeat> itself.
Your code example is confusing, you're basically attempting to perform render="#this", so here's a different and more elaborate example wherein another menu component and some input component are been ajax-updated on change of the current menu:
<ui:repeat ...>
<h:selectOneMenu ...>
...
<f:ajax ... render="otherMenu someInput" />
</h:selectOneMenu>
<h:selectOneMenu id="otherMenu" ... />
<h:inputText id="someInput" ... />
</ui:repeat>
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"

ui:include inside TabView: first ajax call in tab doesn't fire (commandButton action)

The code below is the tabView, followed by the structure of the loaded page. For the commandButton, I have tried actionListener, different combinations of render and update referencing the target inputtextarea (req) explicitly, etc. The action works fine when the form runs in its own page (not within a tab).
In the "preRenderView" event, I initialize data structures, which are populated when the form displays. Problem is when I click on the Preview button. Normally the action fires, the handling method assembles the data for display in the preview inputextarea (req), and it's displayed.
Strangely, when I click the button, the action is NOT called, although there is activity calling my other tabs' loadReqEvents, and in the outer page hosting the tabView. I suspect this is a request-response nuance of JSF that I'm unaware of. Thanks for help.
<p:tabView id="tbv" dynamic= "true" activeIndex="#{sessionController.activeTab}" styleClass="tabview-style">
<p:tab id="rtmTab" styleClass="tab-style" title="RTM" closable="false" titletip="Requirements Traceability Matrix">
<ui:include src="url(./../rtm.xhtml"/>
</p:tab>
<p:tab id="composeTab" styleClass="tab-style" title="#{sessionController.composeTabTitle}" rendered="#{sessionController.crudTabRendered}" closable="false" titletip="Composition Form">
<ui:include src="url(./..#{sessionController.composeUrl}.xhtml"/>
</p:tab>
<p:tab id="objTab" styleClass="tab-style" title="Object / Data Model" closable="false" titletip="Object and Data Model View">
<ui:include src="url(./../objView.xhtml"/>
</p:tab>
</p:tabView>
</p:layoutUnit>
<p:layoutUnit id="formLayout" position="center" gutter="0" styleClass="form-layout">
<h:form>
<f:event listener="#{attrDefController.loadReqEvent}" type="preRenderView"></f:event>
<p:panel style="background-color:rgb(222,231,254);width:925px;height:98%;margin-top:-4px;margin-left:-8px">
<h:panelGrid columns="7" style="margin-right:-8px" cellpadding="2">
<h:commandButton id="preview" value="Preview" action="#{attrDefController.previewReqAction}" style="width:100px; margin-top:2px">
<f:ajax execute="#form" render="req"/>
</h:commandButton>
</h:panelGrid>
</p:panel>
</h:form>
</p:layoutUnit>
Without seeing the markup for where the component req is declared, I assume that it exists in one of the xhtml files specified in the ui:include.
The problem is that the render attribute of the f:ajax is specifying an id which does not exist on the page. The reason for this is that is that the components client ID will be prefixed with the client id of its parent UINamingContainer.
Not all JSF components are a UINamingContainer, form definitely is which is why you will typically see the ID of the form prefixed to the client id of a component. Eg:
<h:form id="formone">
<h:outputText id="textComponent" value="YO" />
<h:commandButton ...>
<f:ajax update="textComponent" />
</h:commandButton>
</h:form>
<h:form id="formtwo">
<h:commandButton ...>
<f:ajax update=":formone:textComponent" />
</h:commandButton>
</h:form>
In the above example the client ID of textComponent is actually formone:textComponent. Now the command button in the example above can still reference it by its Actual ID because it happens to be in the same UINamingContainer as its sibling component.
The commandButton in the other form however must access it by its full client id because it is not a sibling of textComponent. It does this by prefixing the client ID with the universal selector : and then following that with the entire client ID of the textComponent.
Now what does this have to do with your problem?
The PrimeFaces TabView component happens to be a UINamingContainer as well.
So that means that to Ajax render the component with ID req you will need to specify an ID for your form and call it in this way...
render=":formid:tbv:req"
I hope this makes sense.

understanding ajax execute behavior with datatable using jsf 2.0

i'm trying to use an search button which brings back the selected items (can be more than one) and it updates the datatable. Then i have a selectBooleanCheckbox next to each colomn, when user selects "n" items then presses the Select the checked Items it insert DB.
The code can be seen below:
<h:panelGrid columns="5">
<h:form>
<h:outputText value="Item Name"/>
<p:inputText value="#{StockController.itemName}"/>
<h:commandButton value="Search" action="#{StockController.Search}">
<f:ajax execute="#form" render=":results"/>
</h:commandButton>
</h:form>
//The code sample below belongs to BalusC see the post here
<h:panelGroup id="results">
<h:form>
<h:dataTable value="#{bean.entities}" var="entity">
<h:column>
<h:selectBooleanCheckbox value="#{bean.checked[entity.id]}" />
</h:column>
...
</h:dataTable>
<h:commandButton value="Select the checked Items" action="#{StockController.insertDao}" >
<f:ajax execute="#form" render=":results"/>
</h:commandButton>
</h:form>
</h:panelGrid>
Now, i have read many blogs and Core javaServer Faces 3, i don't think there is logical error in ajax usage. I tested by removing each ajax then both works fine but whenever i try to use both of cummondButtons with ajax, the second one "Select the checked Items" does not even call the "StockController.insertDao" method.
Any help is appreciated.
Thanks all.
When you want to ajax-render content which in turn contains another form, then you need to include the ID of that form in the render attribute as well, otherwise the other form will lose its view state and nothing will be processed on submit.
<h:form>
...
<h:commandButton value="Search" action="#{StockController.Search}">
<f:ajax execute="#form" render=":results :resultsForm" />
</h:commandButton>
</h:form>
<h:panelGroup id="results">
<h:form id="resultsForm">
...
</h:form>
</h:panelGroup>
If there's however nothing which goes outside <h:form> inside the same <h:panelGroup>, then you can just omit the <h:panelGroup> altogether and re-render the form directly.
<h:form>
...
<h:commandButton value="Search" action="#{StockController.Search}">
<f:ajax execute="#form" render=":results" />
</h:commandButton>
</h:form>
<h:form id="results">
...
</h:form>
This is related to JSF spec issue 790.
See also:
Communication in JSF2 - Ajax rendering of content which contains another form

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