In JSF 2.2, how to launch a method from a shared menu, wiithout leaving the current page? - jsf

The title says almost all. Just an important precision: the menu is in a template and so is shared by several pages and I don't know the page from which the user will choose the menu item.
I tried with a h:commandLink but I have a problem with the redirection to the same page. Perhaps there is a another kind of solution?

Just make it an asynchronous submit instead of a synchronous submit. Nest in a <f:ajax>.
<h:commandLink ...>
<f:ajax />
</h:commandLink>
If you intend to execute or render some specific parts, specify them accordingly in the execute and/or render attribute of <f:ajax>. They both defaults to #this and #none respectively. E.g.
<h:commandLink ...>
<f:ajax execute="#form" render="#form" />
</h:commandLink>

Related

How to use f:setPropertyActionListener in h:commandButton in JSF without navigation to other pages? [duplicate]

I have a button to submit a form and invoke a managed bean action.
<h:form>
...
<h:commandButton value="Submit" action="#{bean.submit}" />
</h:form>
But when I press the button it refreshes the whole page and sometimes also changes the URL.
Is there some way to not refresh the page and still invoke the action?
Make use of Ajax. It's a matter of nesting <f:ajax> inside the command button of interest.
<h:form>
...
<h:commandButton ...>
<f:ajax execute="#form" render="#none" />
</h:commandButton>
</h:form>
Particularly the render="#none" (which is the default value anyway, you could just omit the attribute altogether) will instruct JSF to re-render just nothing after the submit. If you intend to re-render only a specific component instead of the whole page, then you could also specify the ID of that specific component in render attribute.
<h:form>
...
<h:commandButton ...>
<f:ajax execute="#form" render="result" />
</h:commandButton>
...
<h:panelGroup id="result">...</h:panelGroup>
</h:form>
If you're already using PrimeFaces, then it's a matter of simply using <p:commandButton> instead of <h:commandButton>. It uses by default ajax already, so you don't need to nest in a <f:ajax>. You only need to remember to use attribute names process and update instead of execute and render.
<h:form>
...
<p:commandButton ... update="result" />
...
<h:panelGroup id="result">...</h:panelGroup>
</h:form>
The execute attribute defaults to #form already, so it could be omitted.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?

p:dialog closes when valueChangeListener is invoked

I have a <p:dialog> which contains a <h:selectOneMenu> with a valueChangeListener. Here's the relevant code:
<p:dialog>
<h:form>
<div>
<h:selectOneMenu value="#{itemController.itemId}" valueChangeListener="#{itemController.chkItemType}" onchange="submit()">
<f:selectItems value="#{itemController.itemsList}" />
</h:selectOneMenu>
</div>
</h:form>
</p:dialog>
When it is called, the dialog get closed. I would like to keep it open and only close it on cancel button. How can I achieve this?
That's expected behaviour. The onchange="submit()" which you've there submits the entire form synchronously, causing a complete page reload.
You should be using ajax instead to perform the submit. Replace the onchange attribute by just this tag
<f:ajax />
inside the <h:selectOneMenu>. This way the form will be submitted asynchronously, with by default no page reload at all.
Depending on the concrete functional requirement, which you didn't tell anything about, you do probably also not need a valueChangeListener at all, but rather a <f:ajax listener>.
<f:ajax listener="#{itemController.chkItemType}" />
If you'd like to update some parts of the page on successful execution of the ajax request, use its render attribute.
See also:
When to use valueChangeListener or f:ajax listener?

How make commandButton not fully refresh page? How to use f:ajax?

I have a button to submit a form and invoke a managed bean action.
<h:form>
...
<h:commandButton value="Submit" action="#{bean.submit}" />
</h:form>
But when I press the button it refreshes the whole page and sometimes also changes the URL.
Is there some way to not refresh the page and still invoke the action?
Make use of Ajax. It's a matter of nesting <f:ajax> inside the command button of interest.
<h:form>
...
<h:commandButton ...>
<f:ajax execute="#form" render="#none" />
</h:commandButton>
</h:form>
Particularly the render="#none" (which is the default value anyway, you could just omit the attribute altogether) will instruct JSF to re-render just nothing after the submit. If you intend to re-render only a specific component instead of the whole page, then you could also specify the ID of that specific component in render attribute.
<h:form>
...
<h:commandButton ...>
<f:ajax execute="#form" render="result" />
</h:commandButton>
...
<h:panelGroup id="result">...</h:panelGroup>
</h:form>
If you're already using PrimeFaces, then it's a matter of simply using <p:commandButton> instead of <h:commandButton>. It uses by default ajax already, so you don't need to nest in a <f:ajax>. You only need to remember to use attribute names process and update instead of execute and render.
<h:form>
...
<p:commandButton ... update="result" />
...
<h:panelGroup id="result">...</h:panelGroup>
</h:form>
The execute attribute defaults to #form already, so it could be omitted.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?

JSF - Two Questions about actions on UIComponent

So, let me show us my troubles :)
1 - When i click on a commandbutton
<h:commandButton value="Somethings">
<f:setPropertyActionListener target="#{bean.method}" value="some" />
<f:ajax render="rendering"/>
</h:commandButton>
I dont do any action to the commandButton. Just i fire the ajax call. If i add an action on the button (like action="bean.myAction) it will be executedat the 5° phase of the JSF lifecycle (allright, only if i write event="action" in the f:ajax, but thats as default). Right? But the f:ajax is fired by cliccing on the button as default? Because for a ListBox for example, it's fired only if i write event="change" (the same, i shouldnt write it, because is as default).
2 - When i click on image
<h:graphicImage value="img/img.png" alt="img">
<f:setPropertyActionListener target="#{bean.method}" value="some" />
<f:ajax event="onclick" render="rendering"/>
</h:graphicImage>
This doesnt work. Why?
As usual, thanks for the help!!!!
1 - When i click on a commandbutton
I dont do any action to the commandButton. Just i fire the ajax call. If i add an action on the button (like action="bean.myAction) it will be executedat the 5° phase of the JSF lifecycle
The f:setPropertyActionListener will be executed in the 5th phase as well.
(allright, only if i write event="action" in the f:ajax, but thats as default). Right? But the f:ajax is fired by cliccing on the button as default? Because for a ListBox for example, it's fired only if i write event="change" (the same, i shouldnt write it, because is as default).
The f:ajax just changes the behaviour from a synchronous submit to asynchronous (partial) submit. It does that by generating some additional JavaScript code to the desired event attribute of the parent component (e.g. onclick, onchange, etc, look in generated HTML output in webbrowser). It doesn't change anything in the JSF lifecycle. Only the rendered response will be a partial response which is exactly the part which is to be updated in the component(s) with ID as definied in render attribute.
2 - When i click on image
This doesnt work. Why?
Because the h:graphicImage does not support f:setPropertyActionListener at all. It only works in UICommand components.
You want to wrap it in a h:commandLink instead.
<h:commandLink>
<f:setPropertyActionListener target="#{bean.method}" value="some" />
<f:ajax event="action" render="rendering"/>
<h:graphicImage value="img/img.png" alt="img"/>
</h:commandLink>
(and if necessary style the border/underline caused by generated <a> element away with CSS)

JSF ReRender support with selectBooleanCheckbox

I have a JSF page on which I want to have a checkbox that, when clicked, will add/remove certain other form fields from the page. Here is the (simplified) code I currently have for the checkbox:
<h:selectBooleanCheckbox title="showComponentToReRender" value="#{backingBean.showComponentToReRender}">
<a4j:support event="onsubmit" reRender="componentToReRender" />
</h:selectBooleanCheckbox>
Here is the code for the component I want to hide:
<h:selectOneMenu id="componentToReRender" value="#{backingBean.value}" rendered="#{valuesList.rowCount>1 && backingBean.showComponentToReRender}">
<s:selectItems value="#{valuesList}" var="value"/>
</h:selectOneMenu>
Currently, clicking the checkbox does nothing; that "selectOneMenu" will not go away. What am I doing wrong?
You need to wrap the componentToReRender in either:
<h:panelGroup id="componentToReRenderWrapper">
or
<a4j:outputPanel id="componentToReRenderWrapper">
So, effectively you will have:
<h:panelGroup id="componentToReRenderWrapper">
<h:selectOneMenu id="componentToReRender" value="#{backingBean.value}" rendered="#{valuesList.rowCount>1 && backingBean.showComponentToReRender}">
<s:selectItems value="#{valuesList}" var="value"/>
</h:selectOneMenu>
</h:panelGroup>
and change the reRender="componentToReRenderWrapper" in case you use panelGroup, or remove that attribute, in case you use outputPanel.
Found the exact explanation in the RichFaces docs:
Most common problem with using reRender is pointing it to the component that has a "rendered" attribute. Note, that JSF does not mark the place in the browser DOM where the outcome of the component should be placed in case the "rendered" condition returns false. Therefore, after the component becomes rendered during the Ajax request, RichFaces delivers the rendered code to the client, but does not update a page, because the place for update is unknown. You need to point to one of the parent components that has no "rendered" attribute. As an alternative, you can wrap the component with layout="none" .
Don't forget to set ajaxRendered="true" on the a4j:outputPanel

Resources