Web page :
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:body>
<ui:composition template="../../Template/template.xhtml">
<ui:define name="content">
<h:form>
<h:outputText id="montest" value="#{ProviderLogin.i}"/>
<button class="ZWButtonActionIntervention pfButtonWhite" type="button" onclick="testpageRC()"/>
<span>TESTING</span>
</button>
<p:remoteCommand name="testpageRC" process="#this" update="montest" action="#{ProviderLogin.TESTING()}"/>
<p:commandButton styleClass="ZWButtonActionIntervention pfButtonOrange" value="#{GestionIntervention.m_typeNonTraitee}" action="#{ProviderLogin.TESTING()}"/>
</h:form>
</ui:define>
</ui:composition>
</h:body>
My java class (Bean)
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
#SessionScoped
#ManagedBean(name="ProviderLogin")
public class ProviderLogin implements Serializable
{
private int i;
public int getI(){return i;}
public void TESTING(){i++;}
}
I have a breakpoint in the function 'TESTING()'
When I press the 'p:commandButton', the breakpoint is reached
When I press the 'button' (p:remoteCommand is called), the breakpoint is NOT reached
What is really strange, is that the 'p:remoteCommand' works for this: update="montest"
But, the method in the bean is not fired.
By the way, when I start to write #{... I have access to my bean (variable and methods)
I use Primefaces 6.2
Problem found.
Every web pages defines the content of a template.
In this template there is the section "content" that cointained 2 <h:form>.
One is renderer when the user is not logged.
The other one is rendered when the user is logged correctly.
In each page that re-define the content (when user is logged), i had a second section of <h:form>. It seems that action of the <p:remoteCommand> doesn't manage this well while <p:button> does. I just deleted that form on each pages and my problem was solved.
My template (content part)
<div id="content" style="padding: 10px">
<h:form rendered="#{!ProviderLogin.m_User.m_bLogged}">
<h:button value="Connexion" outcome="/Gestion/Connexion.xhtml"/>
</h:form>
<h:form id="formContent" rendered="#{ProviderLogin.m_User.m_bLogged}">
<ui:insert name="content" >
<ui:include src="content.xhtml" />
</ui:insert>
</h:form>
</div>
One page that re-define the content part (with 2nd form that gave me errors)
<h:body>
<ui:composition template="../Template/template.xhtml">
<ui:define name="content">
<h:form id="formInterventions">
PAGE CONTENT
</h:form>
</ui:define>
</ui:composition>
</h:body>
The same page that re-define the content part (without 2nd form)
then, my action of the <p:remoteCommand> works !
<h:body>
<ui:composition template="../Template/template.xhtml">
<ui:define name="content">
PAGE CONTENT
</ui:define>
</ui:composition>
</h:body>
I also give you this informations :
i use update of some controls like this showcase :
https://www.primefaces.org/showcase/ui/ajax/poll.xhtml
You need to give the id of the control you want to update
When you are using <h:form>, sometimes you need to also specify the id of the form like this :
update="formID:controlID"
Because of that <h:form> defined in my template (which i forgot), it wasn't working because i didn't expect that at all and i didn't give that form an ID, so basically, a default id (j_idt27) was given.
This means my update functionnality couldn't find the specified control id
Related
I have a JSF page that loads the properties of an object (for which the id is passed in the URL). The loading can last more seconds, so I would like to display a wait/busy indicator or a "Loading..." message.
This is done using "viewAction"
<f:metadata>
<f:viewAction action="#{myBean.loadParams}" />
</f:metadata>
Is there a simple way to accomplish this goal? I'm using Primefaces.
PrimeFaces has already a component ready for that: the <p:outputPanel deferred="true">. You only need to make sure that the #{heavyBean} is only referenced in a component (and thus definitely not in a tagfile like <c:xxx> for the reasons explained here) within the <p:outputPanel> and not somewhere else.
...
#{notHeavyBean.property}
...
<p:outputPanel deferred="true">
...
#{heavyBean.property}
...
</p:outputPanel>
...
#{anotherNotHeavyBean.property}
...
Then you can do the heavy job in its #PostConstruct method. Do the job you originally did in <f:viewAction> there in the #PostConstruct.
#Named
#ViewScoped
public class HeavyBean implements Serializable {
#PostConstruct
public void init() {
// Heavy job here.
}
// ...
}
If you need to access properties of other beans, simply #Inject those beans in the HeavyBean. E.g. in case you needed the ID view param:
<f:viewParam name="id" value="#{notHeavyBean.id}" />
#Inject
private NotHeavyBean notHeavyBean; // Also #ViewScoped.
#PostConstruct
public void init() {
Long id = notHeavyBean.getId();
// Heavy job here.
}
The <p:outputPanel> already comes with an animated gif. You can easily customize it via CSS.
.ui-outputpanel-loading {
background-image: url("another.gif");
}
I would like to propose also this simple approach:
one "landing" page (the page where we first navigate in) with a wait indicator and an autoRun remoteCommand with an event that read the parameter "param" from the URL and save it in the bean.
the remoteCommand does a redirect to another page (where the long-running method loadParams is executed)
In this way the wait indicator is shown until the second page is ready to be displayed.
Do you see any weaknesses?
Here the landing page:
<!DOCTYPE html>
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
...
</h:head>
<f:metadata>
<f:event type="postAddToView" listener="#{notHeavyBean.readProperty}" />
<f:viewParam name="param"/>
</f:metadata>
<h:body>
<p:outputPanel layout="block">
<i class="fa fa-circle-o-notch fa-spin layout-ajax-loader-icon" aria-hidden="true" style="font-size: 40px;position: relative;top: 50%;left: 50%;"></i>
</p:outputPanel>
<h:form>
<p:remoteCommand action="#{notHeavyBean.redirect}" autoRun="true"/>
</h:form>
</h:body>
i have a JSF projekt and in there i have different views, which are backed by ManagedBeans.
What i would like to achieve is to change some views while others stay where they are. this has to happen dynamically. In other words. I want to inject and remove views from an xhtml page without a page refresh. I have no clue how to achieve this.
Even better would be a dynamic view injection based on urls. angularjs does that very well.
But even without routing it would be great.
Thanks in advance.
Here is an example in pseudo code:
<nav>
<h:link action="navigationBean.changeView(view1)" method="ajax">Link1</h:link>
<h:link action="navigationBean.changeView(view2)" method="ajax">Link2</h:link>
</nav>
<h:viewContainer>
// view selected by clicking the nav links should be injected here without page reload
</h:viewContainer>
What you ask is better done using Facelet templating. You'll be able that way to have a page template with the shared content (the navigation menu in your case) and make the rest of the views inherit from it.
What can I see from your suggested solution is that you're abusing the POST calls. #{fragmentsPresenter.changeView('viewOne')} doesn't make sense just because you already know where you want to go to when you press that link (to viewOne), So you'll be better using plain links for that.
Here you've got an example showing how to handle navigation in a proper way. Let's suppose you've got a view controller even you won't need it in most of the cases:
ViewController.java
/**
* Give the scope you want to your bean depending on what are your operations
* oriented to. This example could be #ApplicationScoped as well
*
* #author amaeztu
*
*/
#ManagedBean
#SessionScoped
public class ViewController {
/**
* Just gets the current view path and switches to the other one
*
* #return
*/
public String changeView() {
String viewId = FacesContext.getCurrentInstance().getViewRoot()
.getViewId();
if (viewId.equals("/view1.xhtml")) {
return "/view2";
} else {
return "/view1";
}
}
}
This controller's job is just to check what view are you coming from and switch to the other one. It's pointless to perform a POST request (to send a form) just to navigate to the other view, while you could evaluate it before page rendering.
Here you've got how the template view is built:
template.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head />
<h:body>
<h:form>
<!-- Use POST requests like this only when you have
to determine the destination dinamically at server side -->
<h:commandButton value="Switch View with POST"
action="#{viewController.changeView}" />
<br />
</h:form>
<!-- For plain navigation, use GET requests -->
<h:link value="Go to view 1" outcome="/view1" />
<br />
<!-- Determine where we are at page rendering time
and evaluate the other view path -->
<h:link value="Switch view without POST"
outcome="#{view.viewId eq '/view1.xhtml' ? '/view2' : '/view1'}" />
<br />
<br />
<ui:insert name="content" />
</h:body>
</ui:composition>
This template page defines a shared button/link set and calls for content. I've implemented different kind of navigation options. Using <h:link /> is, in this case, the most straight-forward way. Check the second link, here we evaluate the current view id when it gets rendered and a link to go to the opposite one is created. Cool, isn't it?
Now here it is the implementation of the child views:
view1.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" template="/template.xhtml">
<ui:define name="content">
<!-- Here you could have some #ViewScoped
bean managing the content i.e. #{view1Bean} -->
View 1
</ui:define>
</ui:composition>
view2.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" template="/template.xhtml">
<ui:define name="content">
View 2
</ui:define>
</ui:composition>
You'll be able to type their address in your browser and see them, that's what's called bookmarkable ;-)
See also:
Get current page programmatically
Ok, i solved it as follows:
my View:
<h:body>
<nav>
<h:form>
<h:commandLink action="#{fragmentsPresenter.changeView('viewOne')}">
viewOne
<f:ajax execute="#this" render="fragment-container" />
</h:commandLink>
<h:commandLink action="#{fragmentsPresenter.changeView('viewTwo')}">
viewTwo
<f:ajax execute="#this" render="fragment-container" />
</h:commandLink>
</h:form>
</nav>
<h:panelGroup id="fragment-container">
<ui:fragment rendered="#{fragmentsPresenter.activeView('viewOne')}">
<div>i am view one!</div>
</ui:fragment>
<ui:fragment rendered="#{fragmentsPresenter.activeView('viewTwo')}">
<div>i am view Two!</div>
<ui:include src="fragment.xhtml"/>
</ui:fragment>
</h:panelGroup>
and my ManagedBean:
#ManagedBean
#SessionScoped
public class FragmentsPresenter {
private String activeView;
public void setActiveView(String viewName) { this.activeView = viewName; }
public String getActiveView() { return this.activeView; }
public FragmentsPresenter() { this.activeView = "viewOne"; }
public void changeView(String viewName) { this.activeView = viewName; }
public boolean activeView(String viewName) {
return activeView.equals(viewName);
}
}
This question already has answers here:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
Closed 6 years ago.
I have a page that has a preRender call that prepares everything to be displayed in the page. I'm not sure if it's relevant, but the page recieves a few params from the index.xhtml that precedes the experience.
I have a commandButton that I need to execute a server-side method (an update, to be precise). There is no need for a refresh on the page.
So I'm using ajax. Here's the button's, code
<h:commandButton value="Save">
<f:ajax event="click" listener="#{bean.save}"/>
</h:commandButton>
So far, on the java side, here's the bean's save method
public void save(){
log.debug("Save executed!");
}
I've added some logging to check what's being executed. When I click the button, the only thing that happens is that the preRender method is executed (and not entirely, just a part of it). Nothing else happens. Visually, the page is not refreshed or anything.
I suspect that when I click the button, the page is being refreshed and therefore, the preRender method (called Build()) is executed, but since there are no parameters (remember that the Build requires parameters passed through <f:param>), something bugs out.
Bottom line: I just need to execute the save method when clicking on the button without refreshing or redirecting anything.
Ideas?
--EDIT--
INDEX.XHTML
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jstl/core">
<ui:define name="body">
<h:link outcome="agreementDetail.xhtml" value="EA-15558">
<f:param name="serviceId" value="EA-15558" />
<f:param name="site" value="NIC" />
</h:link>
</ui:define>
</html>
AgreementDetail.XHTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jstl/core">
<f:view>
<f:event type="preRenderView" listener="#{agreement.build}"/>
</f:view>
<ui:define name="body">
<f:view>
<h:form>
<h:commandButton value="Save" action="#{agreement.save}">
<f:ajax/>
</h:commandButton><br/><br/>
<h:dataTable value="#{agreement.licenseServerNames}" var="licenseServerName">
<h:column>
<h:inputText value="#{licenseServerName}"/>
</h:column>
</h:dataTable>
</h:form>
</f:view>
</ui:define>
</html>
AgreementBean.java
#ManagedBean(name="agreement")
#RequestScoped
public class AgreementBean {
#ManagedProperty("#{param.serviceId}")
private String serviceId;
#ManagedProperty("#{param.site}")
private String site;
private List<String> licenseServerNames; //GETTERS AND SETTERS OMITTED TO AVOID EXCESS CODE
#PostConstruct
public void build(){
logger.debug("START");
methodOne();
logger.debug("END");
}
public void save(){
logger.debug("SAVE!!!!!");
for(String name : licenseServerNames){
logger.debug("Servername = "+name);
}
}
}
This worked for me."Show" is a boolean that you can set upon successful save.
<h:commandButton id="ajax" value="Save" action="{agreement.save}" >
<f:ajax execute="#form" render="#form" />
</h:commandButton>
<h:outputScript rendered="#{agreement.show}">alert("save");</h:outputScript>
I have some problems with session scoped bean working with f:viewParam. So I have two pages, test_first.xhtml and test_second.xhtml, and a TestBean.java.
first.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head/>
<h:body>
<h:form>
<h:link value="link1" outcome="test_second" >
<f:param name="id" value="1"/>
</h:link>
<br/><br/>
<h:link value="link2" outcome="test_second" >
<f:param name="id" value="2"/>
</h:link>
</h:form>
</h:body>
</html>
second.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<f:metadata>
<f:viewParam name="id" value="#{testBean.userId}" />
</f:metadata>
<h:head/>
<h:body>
<h:form>
This is the second page.
<h:outputText value="Selected id is #{testBean.userId}" />
<h:commandButton value="Print page id" action="#{testBean.print()}" />
<h:commandButton styleClass="submitButton" value="Submit" action="#{testBean.submit}">
<f:ajax execute="#form" render="#form"/>
</h:commandButton>
</h:form>
</h:body>
</html>
TestBean.java:
#ManagedBean
#SessionScoped
public class TestBean implements Serializable{
private Integer userId;
public void print() {
System.out.println(userId);
}
public void submit() {
System.out.println(userId);
}
/...
}
Start running from first.xhtml, if I open link1 in a new tab and then open link2 in another new tab. Now I got two pages.
If I click the "Print page id" button in link1, 1 will be printed in the console. In link2 the printed value will be 2.
But if I click the Submit button in link1, 2 will be printed and the rendered text will change from 1 to 2. (because link2 is opened later and the bean is session scoped?)
(Update: Why is this case? How can I still print "1" if I click "Submit"?)
I want to keep the bean as session scoped for other properties basically. So any thoughts on this or any alternative methods? Many thanks!
If you want it working in different tabs or windows, you need to put those tab specific properties on a ViewScoped or RequestScoped Bean. For properties that are session specific, you could create another Bean and make it SessionScoped.
I have a page split in 3. First part is a list of links which is bound to a mBean (MLeft), and the second is the current mBean (MCenter) of the page I'm in. MCenter inserts data into MLeft so that the links from the first part are custom to the page I'm currently in. The thing is that when the page is rendered and the links are evaluated MLeft is created before MCenter (because is found earlier in the page) and MCenter doesn't get the chance to insert the links in MLeft, so no links are displayed. I put a call to MCenter before the links using an output text referring a dummy property which is an empty string.
I don't like this workaround, I had this problem in the past too with Seam and #Out and I solved it like this. Is there a better approach?
Maybe you can use follow method:
<f:view beforePhase="#{userMB.verifyUser}" />
the method will be invoked when the page be loaded
I think you need to use templates:
template.xhtml
<ui:composition>
<h:head>
<title>
<ui:insert name="title" />
</title>
<h:outputStylesheet name="css/haleczander.css" />
</h:head>
<h:body>
<div class="left">
<ui:include src="static_links.xhtml />
<ui:repeat value="#{links}" var="link">
<h:outputLink value="#{link}">#{link}</h:outputLink>
</ui:repeat>
</div>
<div class="center">
<ui:insert name="content" />
</div>
</h:body>
</ui:composition>
content1.xhtml
<ui:composition template="template.xhtml">
<ui:define name="title">
Content page 1
</ui:define>
<ui:param name="links" value="#{middle.links}" />
<ui:define name="content">
Blah blah 1
</ui:define>
</ui:composition>
I'm assuming links is a list or an array of strings, but you could make anything of it: a list of custom MyLink object, ... (as long as there is an appropriate getter)
You could also replace middle.links with whatever you like, event a method call like #{middle.getLinks(page1)}
Just make Center a managed property of Left. E.g.
#ManagedBean
#RequestScoped
public class Left {
#ManagedProperty(value="#{center}")
private Center center;
#PostConstruct
public void init() {
// Initialize links based on Center here.
}
// ...
}