Unable to do ajax refresh from a composite component - jsf-2

Here is my composite component:
<composite:interface>
<composite:attribute name="attr1" />
<composite:clientBehavior name="xyz" event="valueChange" targets="chkbox" />
</composite:interface>
<composite:implementation>
<h:panelGrid>
<h:panelGroup>
<h:selectBooleanCheckbox id="chkbox"
value="#{cc.attrs.attr1}">
</h:selectBooleanCheckbox>
</h:panelGroup>
</h:panelGrid>
</composite:implementation>
And my page:
<h:form id="myForm">
<cc:myComp attr1="#{myBean.someAttr}">
<f:ajax render="myform:grid1" event="xyz" listener="{myBean.listenerMethod}"/>
</cc:myComp>
<h:panelGrid id="grid1">
<h:panelGroup>
<h:inputTextarea id="rationale" rows="4" cols="70"
value="#{myBean.rationale}" />
</h:panelGroup>
</h:panelGrid>
</h:form>
I'm getting below error:
<f:ajax> contains an unknown id 'myForm:grid1' - cannot locate it in the context of the component chkbox
If I remove render="myform:grid1" from my code then ajax call is working fine. Basically from my composite component I'm not able to refer another OUTSIDE component. How is this caused and how can I solve it?

<f:ajax render="myform:grid1">
Any client ID which does not start with the NamingContainer separator character, which is in your case :, is relative to the closest NamingContainer parent. The closest NamingContainer parent is in your particular case the composite component itself. So, this construct is basically looking for a component with the full client ID myform:XXX:myform:grid1 relative to the composite component, where XXX is the autogenerated ID of the composite component. However, there's no such component with this full client ID.
Assuming that the full client ID of the panel grid is indeed myform:grid1 (i.e. when you open the page in browser, rightclick and View Source, you're indeed seeing <table id="myform:grid1">), then you should make it an absolute client ID instead by prefixing it with the NamingContainer separator character:
<f:ajax render=":myform:grid1">
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"

Related

Does not work properly id generation on ui:repeat My faces 2.2.9 + prime faces 5.3

Actually I'm working with Myfaces version 2.2.9 and I've the following structure to generate any panel according with a specific number selected by the user.
...
<ui:repeat value="#{garajes}" var="garaje" varStatus="loop">
<p:panelGrid >
<h:outputLabel value="Numero de garaje #{loop.index+1}: " />
<h:outputLabel value="Matricula #{loop.index+1}: " />
<p:inputText value="#{garaje.numeroGaraje}" maxlength="5" >
</p:inputText>
<p:inputText id="matriculaInmobiliariaGaraje-#{loop.index+1}" value="#{garaje.matriculaInmobiliaria}"
maxlength="20">
</p:inputText>
...
</p:panelGrid>
</ui:repeat>
....
So, when is rendered the above code the identifiers are weird, has another things like the following image:
So I don't know how to remove this weird things inside of id
Note: I need a specific id to update another component inside of the loop.
What can I do to get a right identifiers inside of ui:repeat?
As to the concrete problem, just give all NamingContainer components a fixed ID. This includes the <ui:repeat> itself.
<ui:repeat id="garajes" ...>
As to the concrete requirement, you're overcomplicating things. A NamingContainer will all by itself worry about uniqueness of IDs of children. Your attempt in id="matriculaInmobiliariaGaraje-#{loop.index+1}" won't work at all as #{loop} variable isn't available during view build time, when the component is being instantiated with id. Get rid of it. You can inside a NamingContainer just use a relative ID to reference another component in the same NamingContainer.
<ui:repeat ...>
<p:inputText id="foo" />
<p:inputText ...><p:ajax ... update="foo" /></p:inputText>
</ui:repeat>
This will work just fine.
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
How to use EL with <ui:repeat var> in id attribute of a JSF component

How to use generated ids in EL (jsf, composite)?

I want to have a composite that composes
<h:form id="f_imgA" >
<h:graphicImage id="imgA"
onclick="document.getElementById('#{k_imgA.clientId}').value=mods(event)"
value="images/img?r=#{Math.random()}">
<f:ajax event="click" listener="#{mBean.handleEvent}"
execute="#this k_imgA" render="#this"></f:ajax>
</h:graphicImage>
<h:inputHidden id="k_imgA" binding="#{k_imgA}" value="#{mBean.keyX}" />
</h:form>
when I write
<comps:cimg imgId="imgA" />
The original purpose of this code is to send the modifier-states (Ctrl, Shift, Alt) to the server.
I have
<composite:interface>
<composite:attribute name="imgId" />
</composite:interface>
<composite:implementation>
<h:form id="f_#{cc.attrs.imgId}">
<h:graphicImage id="#{cc.attrs.imgId}"
onclick="document.getElementById('#{k_${cc.attrs.imgId}.clientId}').value=mods(event)"
value="images/img?r=#{Math.random()}">
<f:ajax event="click" execute="#this k_#{cc.attrs.imgId}"
listener="#{mBean.handleEvent}" render="#this">
</f:ajax>
</h:graphicImage>
<h:inputHidden id="k_#{cc.attrs.imgId}"
binding="k_#{cc.attrs.imgId}" value="#{mBean.keyX}" />
</h:form>
</composite:implementation>
which, quite expected, does not work. The offending expression is
#{k_${cc.attrs.imgId}.clientId}
which is intended to return the clientId of the hiddenInput with id k_imgA . As far as I know, EL cannot handle nested expressions like the one above, but it was worth a try. So is there a simple, straightforward way to get the clientId of k_imgA? I don't want to use more javascript, if this can be avoided.
Edit:
don't get confused about #{Math.random()}, it works just because I have a bean called "Math".
The javascript function mods is given by
<h:outputScript target="body">function mods(event) {return ((event.ctrlKey)?1:0)+((event.shiftKey)?2:0)+((event.altKey)?4:0)} </h:outputScript>
You don't need to fiddle with all those _#{cc.attrs.imgId}. Just give the composite a fixed id. They are already naming containers themselves. JSF will then worry about the rest.
<composite:implementation>
<h:form id="f">
<h:graphicImage id="i" ... />
<h:inputHidden id="k" ... />
</h:form>
</composite:implementation>
Usage:
<comps:cimg id="imgA" />
Generated HTML:
<form id="imgA:f" ...>
<img id="imgA:f:i" ... />
<input id="imgA:f:k" ... />
</form>
As to the JS attempt, you'd best use element's own ID as base:
<h:graphicImage onclick="document.getElementById(id.substring(0,id.lastIndexOf(':')+1)+'k').value='...'" />
Or, easier, if the hidden element is guaranteed to be the direct sibling of the image element in the generated HTML DOM tree, then just grab it by Node#nextSibling:
<h:graphicImage onclick="nextSibling.value='...'" />
<h:inputHidden ... />
The binding will never work as in your attempted construct, and even then you'd best do it via a Map in request scope or a so-called backing component.
See also:
Accessing JSF nested composite component elements in JavaScript
Integrate JavaScript in JSF composite component, the clean way
Rerendering composite component by ajax

Primefaces selectBooleanCheckbox with binding

i am trying to make composite component(multiply use on each view) which allows me to show some inputs by checkbox value. One input is depended on checkbox value. I dont want to bind it to bean cause this value is not saved to database or so. I though that i ll save it in view scope holder.
I ve added in face config holder for bindings
<managed-bean>
<description>Holder of all component bindings.</description>
<managed-bean-name>components</managed-bean-name>
<managed-bean-class>java.util.HashMap</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
</managed-bean>
composite component:
<p:selectBooleanCheckbox binding="#{components[cc.attrs.bindingId]}">
<p:ajax update="panel"/>
</p:selectBooleanCheckbox>
<h:panelGroup id="panel">
<p:inputText rendered="#{components[cc.attrs.bindingId].value}" value="#{cc.attrs.beanPropertyOnTrue}">
<p:inputText rendered="#{not components[cc.attrs.bindingId].value}" value="#{cc.attrs.beanPropertyOnFalse}">
</h:panelGroup>
It works fine, I can use this component multiply on one view, but the problem is when i am using commandButton to send form to server, checkboxes are changing to unchecked....
<p:commandButton value="show decision dialog"
actionListener="#{testBean.action}"
update="#form"
oncomplete="if (args && !args.validationFailed){ dialog.show() }"/>

can't refresh a selectOneMenu

first excuse my english if it's not correct ...
I've a probleme with a primeface's component, I'm trying to refresh a p:selectOneMenu from a p:commandButton, but it's doesn't work (it 's work on another xhtml page, but not here and I can't understand why ...)
First I select an item from an p:autocomplete which update a backingbean's attribute ( for example : userChoose ).
then the p:commandButton is able to call his listener and add userChoose to a list, but i can't refresh the selectOneMenu that display the list. I have to use another p:commandButton to refresh the list.
My form is included into a p:tabMenu in another xhtml page.
<p:autoComplete id="acPojo" value="#{forumBean.user}"
completeMethod="#{autoCompleteBean.completeUser}"
converter="#{userConverter}" forceSelection="true"
var="usr" itemLabel="#{usr.loginUtilisateur}" itemValue="#{usr}">
<p:column>
<h:outputText value="#{usr.loginUtilisateur}"/>
</p:column>
</p:autoComplete>
<p:commandButton value="ajouter" process="acPojo #this "
udpate=":tabView:formSujet:listeUser" actionListener="#{forumBean.addUser}"/>
<p:selectOneMenu value="#{forumBean.user}" converter="#{userConverter}" var="us" id="listeUser"
itemValue="#{us}" itemLabel="#{us.loginUtilisateur}">
<f:selectItems value="#{forumBean.newSujet.listeUserAllowed}" var="User"
itemValue="#{User}" itemLabel="#{User.loginUtilisateur}" />
<p:column>
<h:outputText value="#{us.loginUtilisateur}"/>
</p:column>
<p:ajax process="#this" />
</p:selectOneMenu>
<p:commandButton id="refreshAdmin" icon="ui-icon-arrowrefresh-1-w"
update=":tabView:formSujet:listeUser" />
Thanks for help.
From your code:
udpate=":tabView:formSujet:listeUser"
This has at least 2 (potential) mistakes. The right attribute name is update, not udpate. The one on your other button has however the right attribute name.
It that still doesn't work, then the other potential mistake is that the client ID tabView:formSujet:listeUser does not exist in HTML DOM tree (and thus JavaScript/jQuery is unable to find and replace it). That can happen if the <p:tabView> is dynamic (i.e. you're using <p:tabView value="#{bean.tabs}" var="tab">, because it prepents the tab index number in the final client ID like so tabView:0:formSujet:listeUser if it's the 1st tab.
But, after all, as both the dropdownlist and the commandbutton are in the same NamingContainer parent, you don't need an absolute client ID at all. Just the relative client ID should suffice:
update="listeUser"
Fix that on your both buttons.
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"

f:ajax within ui:repeat, unknown id for the component [duplicate]

This question already has answers here:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
(6 answers)
Closed 7 years ago.
When I try to render a panelGroup by an ajax call, it gives unknown id.
<h:form id="form1" prependId=false>
<h:panelGroup id="panel1">
<h:dataTable/>
<ui:repeat value="#{bean.page}" var="page">
<h:commandLink value="#{page}">
<f:ajax execute="#form" render="panel1" listener="#{bean.page}" />
</h:commandLink>
</ui:repeat>
</h:panelGroup>
</h:form>
When I tried this code, it gives unknown id panel1. I tried with id ":panel1" too. I get the same error.
A relative client ID (i.e. not starting with :) is relative to the current parent NamingContainer component. The <ui:repeat> is also a NamingContainer. So the render="panel1" is looking for the component within the context of <ui:repeat>. This isn't going to work. An absolute client ID (i.e. starting with :) is looking for the component within the context of view root. But you've it inside a <h:form> -which is in turn another NamingContainer component-, so the render=":panel" is also not going to work.
The following should work, with prependId="false" removed so that you can refer it:
<h:form id="form1">
<h:panelGroup id="panel1">
<h:dataTable/>
<ui:repeat value="#{bean.page}" var="page">
<h:commandLink value="#{page}">
<f:ajax execute="#form" render=":form1:panel1" listener="#{bean.page}" />
</h:commandLink>
</ui:repeat>
</h:panelGroup>
</h:form>
By the way, if you actually want to render only the table, then you should be doing this:
<h:form id="form1">
<h:panelGroup>
<h:dataTable id="table1" />
<ui:repeat value="#{bean.page}" var="page">
<h:commandLink value="#{page}">
<f:ajax execute="#form" render=":form1:table1" listener="#{bean.page}" />
</h:commandLink>
</ui:repeat>
</h:panelGroup>
</h:form>
Update: as per the comments, it turns out that you have changed the JSF default NamingContainer separator character from : to _ by configuration. In that case, you need to use _ instead of : in the client ID selector.
<f:ajax execute="#form" render="_form1_panel1" listener="#{bean.page}" />
<ui:repeat value="#{interaction.interactionListBean}" var="interactionItr">
<h:commandLink value="#{interactionItr.interactionDate}" styleClass="#{interaction.createImage}" style="margin:0 5px 5px 0!important; display:inline-block;"><br/>
<f:ajax render=":formId:interactionDate :formId:category :formId:activity :formId:status :formId:channel :formId:status1 :formId:caseId :formId:comment :formId:user1 :formId:team :formId:user :formId:transit "
listener="#{interactionController.interactionDetailGet}"/>
<f:param name="RefId" value="#{interaction.interactionRefId}"/>
</h:commandLink>
</ui:repeat>
problem :
please refer above with above code their is no exception on console but the ajax listerner will not invoke when I saw this post similiar kind of concept being use just I was place the exceute="#form" then my coding is working fine
solution:
execute="#form"

Resources