Unable to update component with rendered="#{initially false}" with Ajax [duplicate] - jsf

I'm trying to ajax-update a conditionally rendered component.
<h:form>
...
<h:commandButton value="Login" action="#{login.submit}">
<f:ajax execute="#form" render=":text" />
</h:commandButton>
</h:form>
<h:outputText id="text" value="You're logged in!" rendered="#{not empty user}" />
However, that does not work. I can assure that #{user} is actually available. How is this caused and how can I solve it?

It's not possible to re-render (update) a component by ajax if the component itself is not rendered in first place. The component must be always rendered before ajax can re-render it. Ajax is using JavaScript document.getElementById() to find the component which needs to be updated. But if JSF hasn't rendered the component in first place, then JavaScript can't find anything to update.
The solution is to simply reference a parent component which is always rendered.
<h:form>
...
<h:commandButton ...>
<f:ajax ... render=":text" />
</h:commandButton>
</h:form>
<h:panelGroup id="text">
<h:outputText ... rendered="#{not empty user}" />
</h:panelGroup>
See also:
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"

Related

h:commandLink renders data table but p:commandLink does not [duplicate]

I'm trying to ajax-update a conditionally rendered component.
<h:form>
...
<h:commandButton value="Login" action="#{login.submit}">
<f:ajax execute="#form" render=":text" />
</h:commandButton>
</h:form>
<h:outputText id="text" value="You're logged in!" rendered="#{not empty user}" />
However, that does not work. I can assure that #{user} is actually available. How is this caused and how can I solve it?
It's not possible to re-render (update) a component by ajax if the component itself is not rendered in first place. The component must be always rendered before ajax can re-render it. Ajax is using JavaScript document.getElementById() to find the component which needs to be updated. But if JSF hasn't rendered the component in first place, then JavaScript can't find anything to update.
The solution is to simply reference a parent component which is always rendered.
<h:form>
...
<h:commandButton ...>
<f:ajax ... render=":text" />
</h:commandButton>
</h:form>
<h:panelGroup id="text">
<h:outputText ... rendered="#{not empty user}" />
</h:panelGroup>
See also:
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?
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: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?

why JSF 2.0 "rendered" does not work without refreshing the page?

When I click a method to render a part of the page, it does not change anything until I manually refresh the page.
Here is the bean:
boolean showPage = true;
public boolean getShowPage(){
return showPage;
}
Here is the view:
<h:form>
<p:commandButton value="Click" action="#{bean.hideContents()}" />
</h:form>
<p:panel rendered="#{bean.showPage}">
Contents
</p:panel>
The panel gets hidden when I manually refresh the page, otherwise it does not.
How is this caused and how can I solve it?
You need to update a parent component of the conditionally rendered component. You can do that by specifying its client ID in the update attribute of the <p:commandButton>:
<h:form>
<p:commandButton value="Click" action="#{bean.hideContents}" update=":panel" />
</h:form>
<h:panelGroup id="panel">
<p:panel rendered="#{bean.showPage}">
Contents
</p:panel>
</h:panelGroup>
See also:
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?

Using jQuery Mobile popup with JSF

Consider the following JSF (& jQuery Mobile) markup:
<h:form>
Please login
<h:outputText id="greeting" value="Welcome, you have logged in" rendered="#{sessionScope.login == null ? false : true}"/>
<div id="login" data-role="popup">
<h:inputText value="#{requestScope.userName}"/>
<h:inputHidden value="#{requestScope.password}"/>
<h:commandButton value="login" action="#{loginBacking.processLogin}">
<f:ajax execute="#form" render="greeting"/>
</h:commandButton>
</div>
</h:form>
Obviously the above markup will not send the user input to the server, because jQuery Mobile popup needs <h:form/> tag inside popup. But if I put the <h:form/> tag inside popup, I cannot use <f:ajax render="greeting"/> (because the id "greeting" left outside).
How can I overcome this issue without using boilerplate Javascript codes?
You can just use absolute client IDs in <f:ajax render>. If you start with the JSF NamingContainer separator character, which defaults to :, then it will be resolved relative to the UIViewRoot. So you can just use render=":greeting".
You've by the way another problem. You cannot update components in JS/Ajax/client side which are by itself not rendered in JSF/server side, simply because there's then nothing in the HTML DOM tree which can be referenced and updated. You need to wrap the <h:outputText id="greeting"> in another component which is always rendered.
So, all with all, this should do for you:
Please login
<h:panelGroup id="greeting">
<h:outputText value="Welcome, you have logged in" rendered="#{login != null}"/>
</h:panelGroup>
<div id="login" data-role="popup">
<h:form>
<h:inputText value="#{requestScope.userName}"/>
<h:inputHidden value="#{requestScope.password}"/>
<h:commandButton value="login" action="#{loginBacking.processLogin}">
<f:ajax execute="#form" render=":greeting"/>
</h:commandButton>
</h:form>
</div>
(note that I have simplified the EL expression in the rendered attribute, it makes no sense to use a conditional operator to return boolean results while the expression by itself already returns a boolean result; I'd myself have preferred rendered="#{not empty login}" by the way)
See also:
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?

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?

Resources