JSF forEach loop values as method parameter - ajax

I think I have a somewhat easy question, I hope.
In my JSF page I use a forEach loop to create buttons to navigate through pages of a table. With ajax I want to render the table according to the clicked page. This looks something like this:
<h:form>
<c:forEach begin="1"
end="#{pages%1 == 0 ? pages : 1+pages-(pages%1)}" step="1"
var="page">
<ui:param name="pageParam" value="#{page}"/>
<h:commandButton value="#{page}">
<f:ajax render="testing" listener="#{properties.setPage(page)}" />
</h:commandButton>
</c:forEach>
<h:outputText id="testing" value="#{properties.getPage()}" />
</h:form>
As you can see, I try to set the page attribute in my bean. But when I click the buttons, I get an exception, that the method was not found (setPage takes int as parameter, but "page" is passed as Byte -> Exception: [...]setPage(java.lang.Byte) ).
So the question is, how can I pass the page number from the forEach as a integer? Is it even possible to pass each generated number to the correlating ajax?

Try something like that:
<c:forEach begin="1" end="#{pages%1 == 0 ? pages : 1+pages-(pages%1)}" step="1" var="page" varStatus="loop">
<ui:param name="pageParam" value="#{page}"/>
<h:commandButton value="#{page}">
<f:ajax render="testing" listener="#{properties.setPage(#{loop.index})}" />
</h:commandButton>
</c:forEach>

Related

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"

How to use <f:ajax> in a plain <form> instead of <h:form>?

I have a search form which uses standard HTML <form> tag and sends a GET request like so search.jsf?country=x&city=y. They are set as view parameters in a view scoped bean.
The search form contains two cascading dropdowns, one for countries and one for cities. How can I update the cities dropdown by <f:ajax> without changing <form> to <h:form> and thus breaking the GET functionality? Do I have to use "plain vanilla" ajax by XMLHttpRequest? How could I use it on a JSF backing bean?
I'd just keep using <h:form> and ask some assistance to JavaScript to turn it into a GET form whenever it's been submitted by the submit button.
Something like:
<h:form prependId="false" onsubmit="doGet(this)">
<h:selectOneMenu id="country" value="#{bean.country}">
<f:selectItems value="#{bean.countries}" />
<f:ajax listener="#{bean.loadCities}" render="city" />
</h:selectOneMenu>
<h:selectOneMenu id="city">
<f:selectItems value="#{bean.cities}" />
</h:selectOneMenu>
<input type="submit" value="Search" />
</h:form>
with this JS to turn it into a GET form and removing the two <h:form> specific hidden fields:
function doGet(form) {
form.method = "get";
form.removeChild(document.getElementsByName(form.name)[1]);
form.removeChild(document.getElementById("javax.faces.ViewState"));
}

Invoke aciton method with input value as parameter

I have this view:
<h:form id="carlin">
<h:outputText id="carlinInput" value="#{userBean.model.varAjax}"/>
<a class="btn" data-toggle="modal" href="#myModal" >Launch Modal</a>
</h:form>
And I have a modal dialog that shows another form:
<h:form>
<h:inputText value="#{userBean.model.varAjax}"/>
<h:commandLink action="#{userBean.processPage1()}" value="Ok">
<f:ajax render=":carlin:carlinInput" />
</h:commandLink>
</h:form>
I need to set the value typed on the <h:inputText> and pass it as a parameter to my <h:commandLink action="#{userBean.processPage1()}" value="OK">`
Here is my processPage1() method:
public void processPage1(String zip) {
this.model.varAjax = zip;
}
I have tried this:
<h:commandLink action="#{userBean.processPage1(userBean.model.varAjax)}" value="OK">
But it doesn't work. If I pass a hardcoded value, it works:
<h:commandLink action="#{userBean.processPage1('teste')}" value="OK">
But I need to pass what the user typed on that inputText to my action method. How can I achieve this?
This is not the right approach. You need to specify the client IDs of the input components which you need to process/execute by the execute attribute of <f:ajax>.
<h:form>
<h:inputText id="varAjax" value="#{userBean.model.varAjax}"/>
<h:commandLink action="#{userBean.processPage1}" value="Ok">
<f:ajax execute="varAjax" render=":carlin:carlinInput" />
</h:commandLink>
</h:form>
This way JSF will set the model value with the submitted value.
public void processPage1() {
System.out.println(model.getVarAjax()); // Look, JSF has already set it.
}
An alternative is to use execute="#form" which will process the entire form and this is what you usually need in standard ajaxified buttons.
<f:ajax execute="#form" render=":carlin:carlinInput" />
Note that componenent libraries like PrimeFaces and RichFaces have already made the #form the default execute attribute, so you don't need to explicitly specify it in their command components. In standard <f:ajax> it namely defaults to #this in command components which is indeed unintuitive.

jsf 2.0 f:ajax render ID not found

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")

Is it possible to disable AJAX in RichFaces?

Is it possible in a Seam/RichFaces page to disable AJAX so requests are sent via regular server-client request, where the entire page is refreshed instead of individual elements? I'm using an a4j:outputPanel and an a4j:commandButton and need to have them not use AJAX in some cases via a toggle button.
Here's a code snippet from the page. Thanks.
<a4j:outputPanel id="output" rendered="#{not empty overtime.overtimeItems}"
ajaxRendered="true">
<c:forEach items="#{overtime.overtimeItems}" var="oc">
<h:outputLabel value="#{oc.dateLabel}"
style="font-weight:#{(oc.id == 1) ? 'bold' : 'normal'}"
for="#{oc.overtimeDateId}" />
<rich:calendar value="#{oc.overtimeDate}"
requiredMessage="Date 1 is required."
id="#{oc.overtimeDateId}" datePattern="MM-dd-yyyy"
required="#{oc.id == 1 ? true : false}" firstWeekDay="0">
<a4j:support event="onchanged"
reRender="#{oc.overtimeHoursId}, #{oc.overtimeHoursOutputId}"
ajaxSingle="true"/>
</rich:calendar>
......
</c:foreach>
</a4j:outputPanel>
<a4j:commandButton action="#{utilities.sendEmail('/pages/overtime/mail.xhtml')}"
type="submit" value="Submit"
reRender="status, valid1, valid2" eventsQueue="foo" status="status"
onclick="this.disabled=false" id="btnSubmit"
oncomplete="#{facesContext.maximumSeverity == null ? 'Richfaces.hideModalPanel(\'mpErrors\');' : 'Richfaces.showModalPanel(\'mpErrors\'); this.disabled=false'}"/>
Only way to do it is to wrap these ajax components in panelgroups and use the rendered property. You'll basically need to provide conditional rendering and provide non-ajax alternatives of the ajax components.
So you would have something like :
<h:panelGroup rendered="#{someBean.ajaxEnabled}">
<a4j:commandButton ..... />
</h:panelGroup>
<h:panelGroup rendered="#{!someBean.ajaxEnabled}">
<h:commandButton ..... />
</h:panelGroup>

Resources