How to know in JSF 1.2 and richfaches the id from h:column in a h:datatable - jsf

I have a datatable from which I open with a click on an image the <rich:modalPanel>. But the <rich:componentControl for="panel" attachTo="showPreview" must have the exact id, in my case below: showPreview, but as my link is inside a dataTable, it will be generated like 1:showPreview 2:showPreview.....n:showPreview
Is there any way to know in which line of the table i am, to get a dynamic binding?
My XHTML in JSF 1.2 looks something like this:
<h:dataTable styleClass="tb_tabletag" id="dtContentPosts" value="#{listOfObjects}" var="object">
<h:column id="columnnumber" >
<h:outputLink id="showPreview" value="#">
<h:graphicImage value="preview.png" />
<rich:componentControl for="panel" attachTo="showPreview" operation="show"
event="onclick"/>
</h:outputLink>
</h:column>
</h:dataTable>
...
...
...
<rich:modalPanel id="panel" autosized="true">
some stuff
</rich:modalPanel>
Thank you for any help!

Thanks Luiggi for your link, with the given source code,this helped me to find my simple trick:
i get now the number with: #{listOfObjects.indexOf(object)}
the only important thing is, that the modalPanel is in a <h:column></h:column> to receive the correct number
works perfect

Related

Bootsfaces command button raises "The subexpression 0 doesn't exist, or it can't be resolved" exception

I am using JSF 2.3 and Bootsfaces 3.3 in a small web application. I stumbled upon a scenario where Bootsfaces' <b:commandButton ajax=true ...> raises an exception while <h:commandButton>+<f:ajax> does not. Looking at the exception that gets raised Bootsfaces is not able to find the element with the given ID that should be updated in the render response phase ("ajaxUpdateMe" in the examples below).
I played around the xhtml page to nail down where the actual problem is and to me it looks like <ui:repeat ...> and an ajaxafied <b:commandButton> is not working well together.
This is the (stripped down version of the) xhtml page that I am using (minus <html> and <head> parts):
<h:body>
<b:form id="formTable">
<!-- iterate over list of objects -->
<ui:repeat value="#{testBean.list}" var="element">
<b:row>
<b:column><h:outputText id="ajaxUpdateMe" value="#{element.name}" /></b:column>
</b:row>
<b:row>
<b:column>
<!-- iterate over another list -->
<h:dataTable value="#{element.innerList}" var="inner">
<h:column>
<b:commandButton ajax="true" value="submit"
action="#{testBean.submit(element)}"
update=":#{component.namingContainer.parent.namingContainer.clientId}:ajaxUpdateMe"
process="#this" />
</h:column>
</h:dataTable>
</b:column>
</b:row>
</ui:repeat>
</b:form>
</h:body>
When I try to access the xhtml page through the browser (GET request) then an exception is immediately raised that looks like this (shortened for sake of brevity):
Caused by: javax.faces.FacesException: Invalid search expression: formTable:j_idt4:0:ajaxUpdateMe The subexpression 0 doesn't exist, or it can't be resolved. net.bootsfaces.component.commandButton.CommandButton formTable:j_idt4:0:j_idt9:0:j_idt13 Additional information: ID not found: 0 search expression: formTable:j_idt4:0:ajaxUpdateMe
at net.bootsfaces.expressions.ExpressionResolver.translateSearchExpressionToId(ExpressionResolver.java:143)
at net.bootsfaces.expressions.ExpressionResolver.getComponentId(ExpressionResolver.java:89)
at net.bootsfaces.expressions.ExpressionResolver.getComponentIDs(ExpressionResolver.java:50)
at net.bootsfaces.expressions.ExpressionResolver.getComponentIDs(ExpressionResolver.java:44)
at net.bootsfaces.component.ajax.AJAXRenderer.generateAJAXCallForClientBehavior(AJAXRenderer.java:582)
at net.bootsfaces.component.ajax.AJAXRenderer.generateBootsFacesAJAXAndJavaScript(AJAXRenderer.java:233)
at net.bootsfaces.component.ajax.AJAXRenderer.generateBootsFacesAJAXAndJavaScript(AJAXRenderer.java:177)
at net.bootsfaces.component.commandButton.CommandButtonRenderer.encodeBegin(CommandButtonRenderer.java:120)
at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:892)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:307)
at com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:114)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:918)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:309)
at com.sun.faces.renderkit.html_basic.TableRenderer.renderRow(TableRenderer.java:398)
at com.sun.faces.renderkit.html_basic.TableRenderer.encodeChildren(TableRenderer.java:161)
I replaced the command button from Bootsfaces with this code here:
<h:commandButton value="submit"
action="#{testBean.submit(element)}">
<f:ajax render=":#{component.namingContainer.parent.namingContainer.clientId}:ajaxUpdateMe"
execute="#this"/>
</h:commandButton>
Now the page loads fine and the command button does what it should do.
Checking the source of the html page in the browser I can see that the element that is mentioned in the exception message formTable:j_idt4:0:ajaxUpdateMe is actually there.
Did I hit a bug in Bootsfaces or am I doing something wrong? Does someone know a workaround where I can still use the command button from Bootsfaces?
It looks like BootsFaces ID resolver strugles with the 0 in formTable:j_idt4:0:ajaxUpdateMe. You can try to add an id="elements to the ui:repeat and then directly reference the target component via :formTable:elements:ajaxUpdateMe.
<h:body>
<b:form id="formTable">
<!-- iterate over list of objects -->
<ui:repeat id="elements" value="#{testBean.list}" var="element">
<b:row>
<b:column><h:outputText id="ajaxUpdateMe" value="#{element.name}" /></b:column>
</b:row>
<b:row>
<b:column>
<!-- iterate over another list -->
<h:dataTable value="#{element.innerList}" var="inner">
<h:column>
<b:commandButton ajax="true" value="submit"
action="#{testBean.submit(element)}"
update=":#formTable:elements:ajaxUpdateMe"
process="#this" />
</h:column>
</h:dataTable>
</b:column>
</b:row>
</ui:repeat>
</b:form>
</h:body>
My IDE does not suggest ui:repeat actually has an id attribute, but it somehow works for me.
Alternatively you can add a standard f:ajax to your button:
<b:commandButton ajax="true" value="submit" process="#this">
<f:ajax render=":#{component.namingContainer.parent.namingContainer.clientId}:ajaxUpdateMe" />
</b:commandButton>
I'm not sure if this is to be considered a bug. You may want to bring this up in their issue tracker

How to show a loading image (using a4j)?

The following code in my .xhtml works fine:
<h:commandButton id="btnConsultar"
action="#cadastrarProponenteBean.consultarCnpj}"
value="#{messages.tx_consultar}"
styleClass="btnAcao" />
But, when I add a4j:support:
<h:commandButton id="btnConsultar"
action="#{cadastrarProponenteBean.consultarCnpj}"
value="#{messages.tx_consultar}"
styleClass="btnAcao">
<a4j:support event="onclick" />
</h:commandButton>
the application breaks, I get strange errors, and my validation messages('getFacesContext().addMessage') are not shown.
Since I'm using a4j:support just to show a loading gif when user clicks, any advice on how to fix this problem?
I'm using JSF and RichFaces.
PS: already tried a4j:commandButton instead of h:commandButton but same problems...
You should use <a4j:status> similar to:
<a4j:status id="ajaxstatus" rendered="true">
<f:facet name="start">
<h:panelGroup>
<h:graphicImage value="/images/loading.gif" />
</h:panelGroup>
</f:facet>
<f:facet name="stop">
</f:facet>
</a4j:status>
I have it in template. Loading image is displayed during any long action.

RichFaces a4j:commandButton. first click does not work the action, it works in the secon click

I have a problem that a I couldn't solve. When I click first time on a a4j:commandButton there is not action. The second and following time it works perfectly. I have read about this problem however I have not clear the solucion.
I am new, and I have find this solucion: (h:commandButton/h:commandLink does not work on first click, works only on second click) however I do not know where should I introduce the script code.
I have found this: however I think is an old jsf version:
(https://community.jboss.org/thread/165031)
And I have tried to repare it with: https://community.jboss.org/wiki/ProgrammaticControlOfPartialProcessingInRichFaces4. However, I have not been success
If someone could explain me the #BalusC solution step by step, it could be really hepful
Thanks very much:
My code is: (everything in the same file)
<ui:define name="table">
<h:form id= "formListCompanies">
<a4j:outputPanel id="tablePaneRegion">
<rich:extendedDataTable ....
<rich:column sortable="false" width="100%">
...
<a4j:commandLink id="editCmd" styleClass="no-decor" render="editGrid, editPane"
execute="#this" oncomplete="#{rich:component('editPane')}.show()">
<a4j:param value="#{it.index}" assignTo="#{myBean.currentIndex}" />
<f:setPropertyActionListener target="#{myBean.selected}" value="#{mypojo}" />
</a4j:commandLink>
....</rich:column>
....
<rich:popupPanel id="editPane" header="#{...}" domElementAttachment="body"
moveable="true" modal="true" resizeable="false" autosized="true"
onshow="focus(#{rich:component('name')});">
....
<!-- h:Inputtext ..-->
<h:panelGrid columns="2">
<a4j:commandButton value="#{'save'}" action="#{myBean.edit}"
render="dataTable" execute="editPaneRegion" />
<a4j:commandButton value="#{...}"
onclick="#{rich:component('editPane')}.hide(); return false;" />
</h:panelGrid>
</h:form>
</a4j:outputPanel>
</rich:popupPanel>
What I have already tried is to take out the h:form id= formListCompanies, and put there a h:panelgrid and a h:panelgroup
Is the problem related to the doble clicking issue? Am i in the right way?
rerender panel and form (form state lost error in jsf spec)... render="richPanelMantenimientoTipoVisualAjaxWebPart,frmMantenimientoTipoVisual"

jsf 2 composite component problem when use f:facet

I am new to JSF, so I have many problems with it. I have solved much, but now I have a problem when I make composite component of column.
This is the code:
myPage.xhtml:
<h:dataTable >
<util:myCol />
</h:dataTable>
myCol.xhtml:
<composite:interface>
</composite:interface>
<composite:implementation>
<h:column>
<f:facet name="header" >
<h:outputText value="user name" />
</f:facet>
<h:outputText value="some data" />
</h:column>
</composite:implementation>
The problem is that the column does not render.
So I have changed a little in code:
myPage.xhtml:
<h:dataTable >
<h:column>
<util:myCol />
</h:column>
</h:dataTable>
myCol.xhtml:
<composite:interface>
</composite:interface>
<composite:implementation>
<f:facet name="header" >
<h:outputText value="user name" />
</f:facet>
<h:outputText value="some data" />
</composite:implementation>
Here the column renders, but the header "user name" does not appear.
How to solve the problem? Thanks in advance.
Case 1:
dataTable only treats column control children as columns. You are adding a composite control to the dataTable and a the column to the composite control.
Case 2:
The problem is probably to do with where the facets are set. These are set on a map on the parent control. The control you are adding the header facet to is the composite control, not the column.
Note: the links are to JSF 1.2 (JEE5) stuff, but the principle still applies.
I don't know if you still follow this thread, but we had problems inserting facets due to a bug.
Starting the content inside the facet with a comment (server side comment < ! - - - - > ) may solve the problem showing the content. We encountered problems with facets having one liners in there.. putting an extra comment as the first statement is the workaround for the problem.
Kind regards,
Gijs
Does it render correctly when you have all of the JSF on one page? Setting up your JSF on a single page at first can be helpful to make sure that the basics are right; after that works, you can break it up into composite components.
Also, I have noticed (using JSF and Richfaces) that sometimes you can't separate 'parents' and 'children' at times; a rich:toolBar and it's rich:toolBarGroup's need to be on the same actual page, for example. I haven't worked with Facelets much so you might have a different situation.
Best of luck.
Edit:
Try pulling the header out of the composite control, i.e.:
<h:dataTable >
<h:column>
*HEADER_FACET_GOES_HERE*
<util:myCol />
</h:column>
</h:dataTable>
Use composite:facet in interface and composite:renderFacet or composite:insertFacet in implementation.
<composite:interface>
<composite:facet name="foo"/>
<composite:attribute name="value"/>
</composite:interface>
<composite:implementation>
<h:inputText id="value" value="#{cc.attrs.value}"/>
<composite:renderFacet name="foo"/>
<composite:insertChildren/>
</composite:implementation>

Absolute reRendering using RichFaces

My problem is that RichFaces reRender does not work 'under' the current element in the element tree; only upper elements get rerendered.
Is there any way to access lower elements with AJAX?
Any help would be appreciated!
Daniel
EDIT I edited this question to a more general one. See revisions if interested in the original question.
reRender works with providing an the id of the target object you want to reRender (inside the same naming container - form most often)
the id should be a unique string, according to html spec
reRender allows dynamic value - i.e. reRender="#{myBean.currentItemsToRerender}
Based on that I think you should be able to achieve what you want (although it's not entirely clear)
Update:
UIComponent.findComponent(..) has a well-defined algorithm for resolving ids. So for absolute referencing your reRendered id should start with : and then continue through the hierarchy of the naming containers.
Here is an example where changePanel111() changes the content of a lower element:
<h:form id="form" prependId="true">
<rich:panel id="PANEL1">
<h:outputText id="PANEL1TEXT" value="#{ajaxTestBean.panel1}"/>
<rich:panel id="PANEL11">
<h:outputText id="PANEL11TEXT" value="#{ajaxTestBean.panel11}"/>
<rich:panel id="PANEL111">
<h:outputText id="PANEL111TEXT" value="#{ajaxTestBean.panel111}"/>
</rich:panel>
</rich:panel>
<rich:panel id="PANEL12">
<h:outputText id="PANEL12TEXT" value="#{ajaxTestBean.panel12}"/>
<br/>
<a4j:commandLink value="CHANGE PANEL12" action="#{ajaxTestBean.changePanel12}">
<a4j:support reRender="PANEL12" event="onclick"/>
</a4j:commandLink>
<br/>
<a4j:commandLink value="CHANGE PANEL111" action="#{ajaxTestBean.changePanel111}">
<a4j:support reRender="form:PANEL111" event="onclick"/>
</a4j:commandLink>
</rich:panel>
</rich:panel>
</h:form>
Notice how the lower element needs to be identified as form:PANEL111.
Hope this helps!
reRender can point to any component outside the form as well. For example this works:
<h:form>
<a4j:commandButton reRender="panel"/>
</h:form>
<h:panelGrid id="panel">
...
</h:panelGrid>
For my MyFaces+Richfaces App, <rich:panel> tag was not working as described in the selected answer. When I changed it to <a4j:outputPanel ajaxRendered="true" />, it started working as given here "<a4j:commandLink> Not Rerendering"
Configuration: MyFaces 2.1.10(Facelets used for templating) and Richfaces 4.2.3.
Hope this will help.

Resources