JSF: Execute values of multiple forms - ajax

I want to submit (execute) values from multiple forms, not just the enclosing form. So, I want to be able to do something like this:
<h:form id="form1>
<h:inputText id="testinput1" value="#{testBean.input1}" />
</h:form>
<h:form id="form2>
<h:inputText id="testinput2" value="#{testBean.input2}" />
<h:commandButton value="Submit">
<f:ajax execute=":form1 :form2"/>
</h:commandButton>
</h:form>
How would you solve this?
What is <f:ajax execute="#all"> really supposed to do? It POSTs only the enclosing form
seems to be related, but addresses a slightly different problem and also does not solve it (or this).

Ajax or not, this is not possible with plain JSF/HTML. All input elements which needs to be processed really needs to go inside the same form.

Related

Populating two components in PrimeFaces

I have a page, that, when I select a Folder name, I populate two Components (<p:selectManyMenu> and <p:pickList>). How to I call two actions?
<p:selectOneMenu id="dirObj"
value="#{patchMB.patchBean.directoryObjetos}"
style="width: 350px">
<p:message for="dirObj"/>
<f:selectItem itemLabel="Selecione" itemValue="Select"/>
<f:selectItems value="#{patchMB.dirObjects}"/>
<f:ajax event="change" listener="#{patchMB.loadFiles}" render="pickListArq"/>
</p:selectOneMenu>
Can I use two <f:ajax> event tags? I tried, and seems that it is executing each listener 2 times.
Here's the code for the second action:
<f:ajax event="change"
listener="#{patchMB.carregarSelectMany}"
render="objSelectMany" />
Why do you need two ajax calling? Couldn't popolate two components using just one action?
Where did you put the second ajax event?
If you want execute two different methods on the same action, you can use a single ajax call and put the logic of the method2 in method1.
Otherwise, evaluate also to use valueChangeListener, it has different behaviour compared to ajax change. Read more on this post:
When to use valueChangeListener or f:ajax listener?

<f:ajax> executing different forms

So I have 2 forms and a command button with f:ajax attached on it. I want to execute the second form on click on button but it seems that it ignores when I'm passing the form's id on execute attribute. But when I replace it with 'execute=":form1"' it runs correctly(the information from the form is sent to server). Can someone tell me why won't work with the id of second form, or how can I achieve this: with one button to execute any form i want from the page.( as it is now no information is sent to server, only the listener is called).
Code bellow:
<h:form id="form1">
<h:panelGrid id="inputSection" >
<h:inputText id="input1" value="#{counterMB.number1}" />
<h:inputText id="input2" value="#{counterMB.number2}" />
</h:panelGrid>
<h:outputLabel id="sumResponse2" value="#{counterMB.sum}" />
</h:form>
<h:form id="form2">
<h:panelGrid id="inputSection" >
<h:inputText id="input1" value="#{counterMB.number1}" />
<h:inputText id="input2" value="#{counterMB.number2}" />
</h:panelGrid>
<h:outputLabel id="sumResponse2" value="#{counterMB.sum}" />
</h:form>
<h:commandButton value="Sum numbers">
<f:ajax event="click" execute=":form2" listener="#{counterMB.sum}" render=":form2 :form1"/>
</h:commandButton>
Update:
so to be more explicit: from what I have read I can use ajax to update/refresh etc some parts of a page instead of refreshing the whole page. What i have tried to do is group some components in different forms and execute a form at a time to see how it behaves. It works perfectly if I use the id of first group(form) but doesn't work at all if I use the id of the second form(it calls the action but doesn't submit any data from any form). I don't understand why. (PS for those who claim i lack some knowledge : this is the reason of asking questions isn't it? I'm trying to learn some new stuff)
It seems that you are lacking basic knowledge of how jsf works. A command button must be inside a form. And it's not possible to submit 2 forms with one single button.
The attribute execute of f:ajax tells which components to process, for example if you have 2 input texts, you can process only one and ignore the other using this attribute. but it's not possible to do what you are trying to do.
It doesn't really make sense to submit 2 forms and execute a single action method once.. there's no point in having 2 forms. why don't you put everything inside a single form?
In your current solution, you use a h:commandButton outside of any h:form - this is a little bit against HTML and JSF, so don't count on it. What I would suggest is
if you use Richfaces, put a a4f:jsFunction in every form and trigger the resulting Javascript from anywhere
if you use Primefaces, put a p:remoteCommand in every form and trigger the resulting javascript from anywhere
if you neither use any of them, put a <h:commandButton /> in every form, set the style hidden and use javascript to submit the form.
Hope it helps...

jsf 2.0 update specific element inside ui:repeat

I'm asking how I can achieve updating a specific element of a loop?
e.g.
<h:form>
<ui:repeat var="element" value="#{bean.elements}" varStatus="status">
<h:outputtext value="#{element.text}" id="#{element.id}" />
<p:commandLink update="#{element.id}" >
<h:outputtext value="UpdateTextField #{element.id}" />
</p:commandLink>
</ui:repeat>
</h:form>
I know that status.index doen't work since its view-rendered. Also the "dynamic" index-setting also doen't work since its view-rendered... But how can i achieve that when the button is clicked, it updates (ajax) the outputtext? Is this only possible with c:forEach?
its ViewScoped and the form must be outside of the loop. otherwise i would solve it with update="#form", but here its not possible
thanks for any help!
Since both ui:repeat and c:forEach generate different dynamic Component Ids for the elements you can't Guarantee the update an individual Item out of all generated items from outside.
I think best approach for this kind of problem would be placing a h:panelGroup around ui:repeat or c:forEach itself and update the h:panelGroupitself.

JSF 2, ajax input field behaves differently in firefox 10 and ie9

When cursor is in input "test" and user press enter-key in a simplified form like
<h:form>
<h:inputText id="test" value="#{myModel.someValue}" >
<f:ajax event="blur" execute="#this" listener="#{myBean.calculateStuff}" render="myText"/>
</h:inputText>
<h:outputText id="myText" value="#{myModel.myText}" />
<h:commandButton value="send" action="#{myBean.calculatedNextPage} ">
</h:form>
firefox invokes 1 submit, ie invokes submit and partial-request.
Is this behaviour ok? From application side it is nuisance, because there is prevention/detection for multiple request on client/server side.
We don't know the page outcome beforehand if some field's validation/conversion has failed and we might not get updated "myText" rendered on both browsers. Enter-key check to prevent from submitting is not desirable and "blur" is good in normal cases. Any suggestions how to get both browser working the same way?
This behaviour is indeed not desired. But MSIE as whole browser at its own also not. That's what you have to deal with as being a web developer. Firefox/Chrome/Safari/etc correctly skip the blur event when the submit event has occurred.
If your sole purpose is to convert/validate someValue, then you should be doing that inside a normal converter and/or validator, not inside an ajax listener method.
<h:inputText id="test" value="#{myModel.someValue}">
<f:converter converterId="someValueConverter" />
<f:validator validatorId="someValueValidator" />
<f:ajax event="blur" execute="#this" listener="#{myBean.calculateStuff}" render="myText"/>
</h:inputText>
This way you can just safely ignore "unnecessary" ajax requests.
But if you really have a hard head in, you can in your particular example always add an onsubmit handler to skip the onblur.
<h:form id="form" onsubmit="document.getElementById('form:test').onblur=null">

How to inject one JSF2 page into another with jQuery's AJAX

I'm using jQuery's .load function to load one JSF page into another.
This works really well until the loaded JSF page uses some AJAX functionality. When this happens, the parent JSF page's AJAX stops working. In fact, after the two pages are combined whichever page has its AJAX called next is the one that continues to work. The other page stops working. If I use the parent page first, the child breaks. If I use the child first, the parent breaks.
Am I doing something wrong? I'm guessing JSF isn't designed for this sort of behaviour and that's fine but then how do I go about doing what I want?
Basically, we have a report page. When the user clicks the link to a report we would like the report to load dynamically into the existing page. That way, the user doesn't experience a page refresh. It's a pretty slick behaviour BUT obviously isn't ideal due to the pages breaking.
I suppose I could do this with a page that contains every report in an outputpanel and then determine which one is rendered based on a value in the backing bean but I can see lots of occasions where I'd like to be able to "inject" one page into another (for dynamic dialogs for instance) and it would suck to have to keep everything in one giant template.
Has anyone else come across this sort of problem? How did you solve it?
Do not use jQuery.load(). It does not take JSF view state into account at all, so all forms will fail to work. Rather make use of <f:ajax> and rendered attribute instead. Here's a basic example:
<h:form id="list">
<h:dataTable value="#{bean.reports}" var="report">
<h:column>#{report.name}</h:column>
<h:column>
<h:commandLink value="Edit" action="#{bean.edit(report)}">
<f:ajax render=":edit" />
</h:commandLink>
</h:column>
</h:dataTable>
</h:form>
<h:form id="edit">
<h:panelGrid columns="3" rendered="#{not empty bean.report}">
<h:outputLabel for="name" value="Name" />
<h:inputText id="name" value="#{bean.report.name}" required="true" />
<h:message for="name" />
...
<h:panelGroup />
<h:commandButton value="save" action="#{bean.save}" />
<h:messages globalOnly="true" layout="table" />
</h:panelGrid>
</h:form>
You can if necessary split off the content into an <ui:include>.

Resources