Invoke <h:commandLink> action method using <f:ajax> - ajax

I have the following code:
<h:commandLink action="#{testBean.showSomething}">
Do Stuff
</h:commandLink>
which does what I want (change the state of testbean and reload the page which will show a different set of divs. because of their "rendered" properties)
Now I want to use ajax to accomplish this so I did this:
<h:commandLink action="#{testBean.showSomething}">
<f:ajax event="click" render=":content" />
Do Stuff
</h:commandLink>
However this causes the showSomething method to not even be called.
IMHO what I want to do is rather simple but I can't for the life of me figure out how to do it.

You need to use event="action" instead of event="click". You could even omit it altogether. It's namely the default event the <f:ajax> is listening on when nested in an UICommand component.
<h:commandLink action="#{testBean.showSomething}">
<f:ajax render=":content" />
Do Stuff
</h:commandLink>

Related

f:ajax render form component

I want to render a single component (h:selectManyCheckbox) inside a form based on a check-box that I select or not.
<h:form>
<h:selectBooleanCheckbox value="#{bean.var}">
<f:ajax event="click" render="employeeCheckboxes" />
</h:selectBooleanCheckbox>
<h:selectManyCheckbox
id="employeeCheckboxes"
value="#{bean.checkboxes}"
rendered="#{var}">
</h:selectManyCheckbox>
</h:form>
However, the component isn't re-rendered on selecting or deselecting the check-box. I can however re-render the whole form but I don't want that.
You can't reference a component in <f:ajax render> which is in first place never rendered in HTML output. The <f:ajax render> uses under the covers JavaScript document.getElementById() to find the HTML element in order to update it with the new HTML structure from the ajax response. However, if a JSF component is in first place never rendered in HTML output, then JavaScript can't find it anywhere either.
You need to wrap it in another component which is always rendered.
<h:form>
<h:selectBooleanCheckbox value="#{bean.var}">
<f:ajax render="employeeCheckboxesGroup" />
</h:selectBooleanCheckbox>
<h:panelGroup id="employeeCheckboxesGroup">
<h:selectManyCheckbox
id="employeeCheckboxes"
value="#{bean.checkboxes}"
rendered="#{bean.var}">
</h:selectManyCheckbox>
</h:panelGroup>
</h:form>
(note that I removed event="click" as it's the default already)
See also:
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?
Hi i think you missed managed bean name in
rendered attribute
of checkbox tag.

jsf listener not called inside nested ui:repeat

I have a problem using ui:repeat nested in each other where I'd like to call a listener. I have also tried c:forEach instead, but got the same problem.
For demonstrating the problem I have simplified the code to the problem.
There are two buttons, the first inside the first ui:repeat, calling successful a simple listener. The second button is inside the nested ui:repeat element, should call the same listener as the first button, but the listener is never called.
Can you please tell me whats wrong with this?
<div>
<ui:repeat var="testList" value="#{testBean.testList}">
<h:commandButton value="test1">
// the listener is called if I click this button
<f:ajax event="click" execute="#this" listener="#{testBean.testListener}" />
</h:commandButton>
<ui:repeat var="nestedList" value="#{testList.nestedList}">
<h:commandButton value="test2">
// the listener will not be called if I click this button
<f:ajax event="click" execute="#this" listener="#{testBean.testListener}" />
</h:commandButton>
</ui:repeat>
</ui:repeat>
</div>
This is a known Mojarra issue related to broken state management of <ui:repeat>. Specifically this issue is reported as issue 1817 and fixed since Mojarra 2.1.15.
Upgrade your Mojarra version. It's currently already at 2.1.19.

JSF ajax commandbutton not updating primefaces picklist

This is the code:
<h:form id="articleForm" >
<p:commandButton value="Select tags" ajax="true" >
<f:ajax execute="#form" render="#form :articleForm:tags" />
</p:commandButton>
<p:pickList id="tags" value="#{articleController.dualListModelForTags}" var="tag" itemLabel="#{tag.tag}" itemValue="#{tag}" converter="distinctTagConverter">
<f:facet name="sourceCaption">Distinct tags</f:facet>
<f:facet name="targetCaption">Connected tags</f:facet>
</p:pickList>
</h:form>
When the commandbutton is clicked, the getDualListModelForTags() in the backing bean is called and executed. In getDualListModelForTags() I make some modifications so I want the picklist to be updated. But the picklist(id=tags) is not rendered again. Only when I refresh the page, are the modifications made to the picklist.
The PrimeFaces <p:commandButton> component doesn't work together with <f:ajax>. You need to use the button's own ajax-targeted attributes instead. Instead of the <f:ajax execute> you should use <p:commandButton process>. But this already defaults to #form, so you can omit it. Instead of the <f:ajax render> you should use <p:commandButton update>. Specifying client IDs which are already covered by #form is unnecessary, so just #form is sufficient. Also the ajax="true" attribute is unnecessary as that's the default already.
So just this should do:
<p:commandButton value="Select tags" update="#form" />
Unrelated to the concrete problem, you're doing the business job inside a getter method. This is a bad idea. Do it in the button's action method instead. You also seem to be using a session scoped bean for view scoped data. This is a bad idea. Put the bean in the view scope instead.

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>.

Ajax, conditional rendering and backing beans

I am trying to display a page where the user, by the appropriate selection using a radio button, sees either a textbox or a combo box. This is relatively easy and I managed to do that by the following code:
<h:selectOneRadio id="selection" value="#{inputMethod.choice}">
<f:selectItem itemValue="#{inputMethod.TEXT}" itemLabel="textbox"/>
<f:selectItem itemValue="#{inputMethod.COMBO}" itemLabel="combobox" />
<f:ajax event="click" execute="#this" render="#form" />
</h:selectOneRadio>
<h:panelGroup id="Textbox" rendered="#{inputMethod.choice==inputMethod.TEXT}">
<h:outputLabel>Textbox:</h:outputLabel>
<h:inputText value="#{myBean.somevalue}" />
</h:panelGroup>
<h:panelGroup id="Combobox" rendered="#{inputMethod.choice==inputMethod.COMBO}">
<h:outputLabel Combobox:/>
<h:selectManyListbox id="CommunityListbox" value="#{myBean.choices}">
<f:selectItems value="#{myBean.selections}" var="u" itemValue="#{u.id}" itemLabel="#{u.name}"/>
</h:selectManyListbox>
</h:panelGroup>
The problem I have is that the setter for the combo box is never called.
In fact, the setter is only called for the component that is rendered by default (in this case whenever inputMethod.choice==inputMethod.TEXT). If I remove the conditional rendering, all setters are called as one would expect.
Any ideas or answers will be greatly appreciated!
PS: I am using jsf2.0, Glassfish 3.1, Netbeans 7.0 (in case this is of any importance)
You need to ensure that #{inputMethod.choice} evaluates exactly the same during the request of processing the form submit as it did during the request of displaying the form. Easiest is to put the bean in the view scope or to move the initialization logic into the (post)constructor of the request scoped bean.

Resources