Pass parameter to f:ajax inside c:foreach loop - jsf

I am trying to pass a parameter to an ajax event, this is an example of what I mean:
<h:panelGrid id="pictures" columns="3">
<c:forEach items="#{createProduct.pictures}" var="picture">
<h:graphicImage value="#{picture.source}" />
<h:inputText value="#{picture.alt}" />
<p:commandButton value="Remove">
<f:ajax execute="#form"
listener="#{createProduct.removePicture(picture)}"
render="#form" />
</p:commandButton>
</c:forEach>
</h:panelGrid>
I know this code won't work because you cannot pass a parameter through the ajax listener. Though this is merely an example of what I am trying to accomplish. I have tried using <f:param id="picture" value="#{picture}" /> allong with the ajax tag, though this results in a duplicate component ID form:picture since it is in a loop.
I need this parameter inside the method in order to determine which picture to remove.
How can I solve this with ajax?
I am using a #ViewScoped CDI-bean.

First, I suggest replacing c:forEach with ui:repeat tag. Second, as you are using Primefaces, you should use all its strength. So, commandButton can be more easily written:
<p:commandButton value="Remove" process="#form" update="#form" action="#{createProduct.removePicture(picture)}"/>
and that's it. Don't complicate.
By the way, primefaces commandButton is sends AJAX request by default, you don't need (and you must not use) f:ajax tag.

Related

h:commandButton not working [duplicate]

How to update a div and do partial submission using <h:commandButton>, I have previously used <p:commandButton> to do partial submission by setting the ajax attribute to true and the update attribute to :statusBlock, where the id of the <h:panelGroup> is statusBlock. I am having some designing issues with <p:commandButton> so I cannot use it so I have to use <h:commandButton>.
This is to be done by nesting a <f:ajax> in it.
In effects,
<p:commandButton ... process="#form" update=":statusBlock" />
does exactly the same as
<h:commandButton ...>
<f:ajax execute="#form" render=":statusBlock" />
</h:commandButton>
Note that the subtle difference with the PrimeFaces equivalent is that PrimeFaces defaults to #form in the process/execute, while the <f:ajax> one defaults to #this, so you might need to explicitly specify execute="#form" over all place where you didn't specify the process attribute in the PrimeFaces component.
See also:
Communication in JSF 2.0 - Ajax (asynchronous) POST form
You can just use the standard components alongside f:ajax e.g.
<h:form id="myForm">
<h:commandButton value="Push Me">
<f:ajax execute="myForm" render="statusBlock" />
</h:commandButton>
<h:panelGroup id="statusBlock">
</h:panelGroup>
</h:form>

JSF rendered method is not invoked in the second time

I have next a4j:jsFunction
<a4j:jsFunction name="renderOnBusinessErrorEvent" execute="#none" bypassUpdates="true" immediate="true"
render="securityForm">
</a4j:jsFunction>
and JSF form with some dialog inside
<h:form id="securityForm">
<h:panelGroup rendered="#{someCondition}">
......
</h:panelGroup>
</h:form>
In my business logic it has to be executed twice consequently. In the first time all is fine. Rendered method is invoked and the expected dialog is present on the page. In the second time rendered method is not invoked, but model has been changed and I expect that dialog will not be present on the page. I supposed that it's some richfaces issue and I tried to use f:ajax
<a4j:jsFunction name="renderOnBusinessErrorEvent" execute="#none" bypassUpdates="true" immediate="true">
<f:ajax event="begin" render=":securityForm"/>
</a4j:jsFunction>
but unsuccessfully. Rendered method still not invoked in the second time. What is it? Some JSF optimization or bug? What's the workaround?
JSF version 2.1.19
The problem was in <h:panelGroup rendered="#{someOtherCondition}">
over h:form which equals false after the first rendering (ON THE SERVER SIDE).
However, this panelGroup is not part of rendering. So, my code:
<h:panelGroup rendered="#{someOtherCondition}">
<h:form id="securityForm">
<h:panelGroup rendered="#{someCondition}">
......
</h:panelGroup>
</h:form>
</h:panelGroup>
<h:form>
<a4j:jsFunction name="renderOnBusinessErrorEvent" execute="#none" bypassUpdates="true" immediate="true"
render="securityForm">
</a4j:jsFunction>
</h:form>
Before calling renderOnBusinessErrorEvent() I'm changing the value of someOtherCondition from true to false, but I don't rerender this element. Actually, on the server side this element is already missing. Looks like it's JSF feature, but is it specificated somewhere?

Trigger actionListener with partialSubmit

I have the following code:
<h:panelGrid columns="2" styleClass="labelValueContainer" columnClasses="one,two">
<p:outputLabel value="Value" />
<p:inputText id="englishValue" styleClass="englishValue" value="#{labelsManager.addLabelsBean.engValue}" />
</h:panelGrid>
<p:commandButton value="COPY" styleClass="copyButton" process="englishValue" partialSubmit="true" actionListener="#{labelsManager.setValueForCopy}">
What I'm trying to do is to submit only one inputText and trigger an actionLister (or an action) with ajax. If I remove partialSubmit="true" the method "setValueForCopy" is trigger but when I add again actionListener is not triggered anymore and I don't know way.
If anyone have a better solution for submiting an input and trigger a method I'm ready to listen.
Thanks!
When using partialSubmit="true", only things in process="..." will be submitted (and processed). This is missing the <p:commandButton> itself.
Add it via #this:
<p:commandButton ... process="#this englishValue" partialSubmit="true" ... />
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes

How to execute h:commandButton actionListener before onclick?

I need some help in the below code
<h:commandButton id="WhatifButtonID" value="#{demandBean.dmdReviewScreenLabelVO.whatIf}" style="width:60px; height:22px;" actionListener="#{demandBean.whatif}" onclick="window.open('DemandTargetList.xhtml','whatif','width=460,height=280,top=150,left=350,resizable=no,scrollbars=no')" >
<f:ajax execute="#this" ></f:ajax>
</h:commandButton>
In the above case, the onclick attribute gets executed first followed by the actionlistener attribute. I wanted the actionListener attribute to get executed first followed by the onclick function, since the page that loads onclick needs to get certain values from the actionListener. Please let me know how to acheive the same. Thanks in Advance.
Just let <f:ajax> render a script on complete.
<h:commandButton value="#{demandBean.dmdReviewScreenLabelVO.whatIf}" actionListener="#{demandBean.whatif}">
<f:ajax execute="#this" render="popupScript" />
</h:commandButton>
<h:panelGroup id="popupScript">
<h:outputScript rendered="#{demandBean.whatifPressed}">
window.open('DemandTargetList.xhtml','whatif','width=460,height=280,top=150,left=350,resizable=no,scrollbars=no');
</h:outputScript>
</h:panelGroup>
wherein you set whatifPressed to true in the whatif() method.
PrimeFaces may help with this with the use of the <p:remoteCommand/> tag. You can then just use a plain old button to call the remoteCommand, then simply execute the window.open().
<p:remoteCommand name="viewSomething" actionListener="#{someActionIWantToExecuteBeforeOpeningWindow}" update="#this" process="#this"/>
<button onclick="viewSomething(); window.open('http://somewhere.com', 'windowName', 'height=924,width=723');">Click me!</button>
You can use it over lists of items if you call the javascript function it creates something unique.

Why doesn't h:commandButton execute the action method when combined with c:chose?

I've seen a strange problem in my project. It's that <h:commandButton/> does not execute the action method.
<c:choose>
<c:when test="#{empty param.t}">
// HTML
</c:when>
<c:when test="#{param.t eq 'normal'}">
// HTML
<h:form>
<h:commandButton value="ADD" action="#{addBean.doSomething}" />
</h:form>
<c:when>
</c:choose>
When I move <h:form> into first c:when, then the action method is called. Otherwise, it isn't. Why?
I'll ignore the syntax error in your EL (a missing }).
The command button won't be executed when #{param.t eq 'normal'} evaluates to false at the point the form submit request is to be processed. You need to maintain the same parameter for the subsequent request so that the button will be rendered so that JSF can confirm that the enduser is allowed to invoke the action. You can do this by adding a <f:param>:
<h:form>
<h:commandButton value="ADD" action="#{addBean.doSomething}">
<f:param name="t" value="#{param.t}" />
</h:commandButton>
</h:form>
Note that this is supported since JSF 2.0 only. On JSF 1.x you'd need to replace h:commandButton by a h:commandLink if you want f:param support.
Unrelated to the concrete problem, you should try to avoid JSTL as much as possible in your JSF views. If the intent is to render view parts conditionally (not to build view parts conditionally), then you should rather be using the JSF component's rendered attribute instead of a JSTL <c:choose> or <c:if>:
<h:panelGroup rendered="#{empty param.t}">
// HTML
</h:panelGroup>
<h:panelGroup rendered="#{param.t eq 'normal'}">
// HTML
<h:form>
<h:commandButton value="ADD" action="#{addBean.doSomething}" />
</h:form>
</h:panelGroup>

Resources