Completely edited:
Maybe I was mixing problems and misinterpreted. After simplifying my code the question simplifies to: How can I prevent the <p:commandButton> from executing it's action method on page refresh (like when you hit F5 inside browser window)?
JSF Code:
<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:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:body>
<h:form>
<h:outputText value="#{bugBean.number}" />
<h:outputText value="#{bugBean.isComplete()}" />
<p:commandButton id="entryCommand" value="add"
action="#{bugBean.increase()}" update="#form" oncomplete="#{bugBean.complete()}"/>
</h:form>
</h:body>
</html>
backing bean code:
package huhu.main.managebean;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#Named
#SessionScoped
public class BugBean implements Serializable {
private static final long serialVersionUID = 1L;
private int number;
private boolean isComplete = false;
public void increase(){
number++;
}
public void complete(){
isComplete = true;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public boolean isComplete() {
return isComplete;
}
public void setComplete(boolean isComplete) {
this.isComplete = isComplete;
}
}
Update:
Even if I remove the oncomplete stuff like this an click the <p:commandButton> just once, the counter goes up on every page refresh.
<h:form>
<h:outputText value="#{bugBean.number}" />
<p:commandButton id="entryCommand" value="add"
action="#{bugBean.increase()}" update="#form"/>
</h:form>
The construct was lacking Ajax-support due to a missing head definition as it seems. In this case I just added <h:head/> right above the <h:body>-tag and everything worked fine.
Thanks to all contributors!
I think that the action method increase() is not called on each page refresh, but it's called the complete() method instead, and this is probably making you think that the action method has been called.
The oncomplete attribute inside the p:commandButton indicates a client side action, and so a JS method, and not a server action: the EL executes #{bugBean.complete()} when parses it on each page refresh.
Related
This question already has an answer here:
#SessionScoped bean looses scope and gets recreated all the time, fields become null
(1 answer)
Closed 4 years ago.
This is my first question.
I am trying to increment a variable value in a textbox when a button is clicked using primefaces.
But through debug I found out that whenever I click the p:commandButton, EL bean function call, tries to increment the bean class variable "counter", whenever this happens the value of counter is always 0, so it gets incremented to 1 and that is shown in my webpage. It never reaches 2, 3, 4...
Below is the code:
xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<h:form>
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel value="Counter:"/>
<h:outputText id="output" value="#{counterView.counter}" />
<p:commandButton value="Count" action="#{counterView.increment}" update="output" />
</h:panelGrid>
</h:form>
</h:body>
</html>
Java:
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.view.ViewScoped;
#ManagedBean(name="counterView")
#ViewScoped
public class counterView implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2369382392318418242L;
private int counter = 0;
public int getCounter() {
return counter;
}
public void setCounter(int counter) {
this.counter = counter;
}
public void increment() {
// Counter is 0 always the moment this function is entered...
this.counter = this.counter + 1;
}
}
I cant figure out where I am going wrong as its a classical example in primefaces showcase and I am following that...
Thanks in advance
You use the wrong ViewScoped annotation. You have to use the javax.faces.bean.* annotations in combination with #ManagedBean.
see: #SessionScoped bean looses scope and gets recreated all the time, fields become null
I have problem using JSF 2.0. The command button doesn't call the bean, I have already read the balusc answer commandButton/commandLink/ajax action/listener method not invoked or input value not updated but I don't think I'm encountering those cases,
this is the code I'm using:
<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"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jstl/core">
....
<ui:repeat var="skill" value="#{skillsView.skills}">
<h:form>
<h:commandButton value="#{skill}"
action="#{skillsController.removeSkillFromPublication}" ajax="true">
<f:param name="theskill" value="#{skill}" />
</h:commandButton>
</h:form>
</ui:repeat>
</ui:composition>
UPDATE 1 :
this my controller
#Controller
#Scope(value = WebApplicationContext.SCOPE_REQUEST)
public class SkillsController extends BController {
private static final Logger logger = LoggerFactory
.getLogger(SkillsController.class);
public void removeSkillFromPublication() {
logger.info("Deleting : " + getParameter("theskill"));
publicationService.removeSkillFromPublication(publicationDetailView
.getPublicationFullView().getId(), getParameter("theskill"));
skillsView.setSkills(publicationService
.getSkillsFromPublication(publicationDetailView
.getPublicationFullView().getId()));
}
}
i don't get the the logger neither the task is executed , i already tested with actionlistner with controller with actionevent and this doesent work
UPDATE 2 :
It's working with changing the SCOPE of the skillsView To WebApplicationContext.SCOPE_SESSION , anybody know why ?!!
#Controller
#Scope(value = WebApplicationContext.SCOPE_SESSION)
public class SkillsView {
List<String> skills;
private String currentSkill;
public List<String> getSkills() {
return skills;
}
public void setSkills(List<String> skills) {
this.skills = skills;
}
public String getCurrentSkill() {
return currentSkill;
}
public void setCurrentSkill(String currentSkill) {
this.currentSkill = currentSkill;
}
The h:commandButton attribute action requires you to return a String
Taken from the jsf-toolbox:
action
The action attribute accepts a method-binding expression for a backing bean action method to invoke when this component is activated by the user. An action method must be a public method with no parameters that returns a String. The returned string represents the logical outcome of the action (eg. "success", "failure", etc. ) and is used by the JavaServer Faces MVC framework to determine which view to display next.
[bolding by me]
Instead use the actionListener property:
<h:commandButton actionListener="${skillsController.removeSkillFromPublication()}" ajax="true">
<f:param name="theskill" value="#{skill}" />
</h:commandButton>
Keep in mind you will have to change the method-signature to have an ActionEvent as parameter:
public void removeSkillFromPublication(ActionEvent e) {
//...
See the toolbox:
actionListener
The actionListener attribute accepts a method-binding expression for a backing bean action listener method that will be notified when this component is activated by the user. An action listener method must be a public method with an ActionEvent parameter and a void return type.
Alternatively you could have your removeSkillFromPublication() return a String. But that seems to be the wrong approach here.
I have a component on my view which i want to update from my bean.
It works only once. If i press the second button nothing happen, but the bean method in the actionlistener was called.
I checked the browser log with firebug and have no errors or something else which looks odd.
My Bean is in ViewScope. I'm using primefaces 3.5.
JSFPage:
<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:body>
<h:form id="myRootForm">
<p:inputText id="text1" styleClass="myChangeClass" disabled="true" />
</h:form>
<h:form>
<p:commandButton value="Activate Insert"
actionListener="#{controller.activate()}" update=":myRootForm" />
<p:commandButton value="Deactivate"
actionListener="#{controller.resetFields()}" update=":myRootForm" />
</h:form>
</h:body>
</html>
This is the EJB code:
import javax.faces.component.UIViewRoot;
import javax.faces.component.html.HtmlInputText;
import javax.faces.context.FacesContext;
import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.ViewAccessScoped;
import java.io.Serializable;
import javax.inject.Named;
#ViewAccessScoped
#Named("controller")
public class Controller {
private UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();
public void activate() {
HtmlInputText text = (HtmlInputText)
viewRoot.findComponent("myRootForm:text1");
text.setDisabled(false);
RequestContext.getCurrentInstance().update(text.getClientId());
}
public void deactivate() {
HtmlInputText text = (HtmlInputText)
viewRoot.findComponent("myRootForm:text1");
text.setDisabled(true);
RequestContext.getCurrentInstance().update(text.getClientId());
}
}
** Update:
I made the example a bit better to read.
When i'm using the "RequestScope" it is working, but i need the viewScope to hold my information.
For a better understanding why i want to do it this way:
I have several input components which i want to be available in several mode's.
The mode is indicated in a StyleClass (i.e. myChangeClass).
When i press the button i go through the component tree of my form and searching for the styleclass and activiate the buttons. I don't want to do this by holding for every component an attribute in my bean.
I don't know exactly what you're trying to achieve. I've added example below to help you.
XHTML code
<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>
<title>Test</title>
</h:head>
<h:body>
<h:form id="myRootForm">
<p:inputText id="text1" disabled="#{tBean.enabled}" />
<p:commandButton value="Activate Insert"
actionListener="#{tBean.enable}" update=":myRootForm" />
<p:commandButton value="Deactivate" actionListener="#{tBean.disable}"
update=":myRootForm" />
</h:form>
</h:body>
</html>
ManagedBean Code
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
#ManagedBean(name = "tBean")
#ViewScoped
public class TestBean {
private boolean enabled;
public void enable(ActionEvent e) {
enabled = false;
}
public void disable(ActionEvent e) {
enabled = true;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
Try above and see if that helps.
I am working on JSF2.0 project where I need to get value in backing bean from previous screen I have explained it below
my first screen
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
>
<h:body>
<h:form>
<h:outputText value="LocationID" />
<h:inputText value="#{getDetails.locationID}"/>
<h:commandButton value="Add OS" action="#{getDetails.addOSDetails}"/>
</h:form>
</h:body>
</html>
My backing bean when the commandButton is invoked
#ManagedBean(name="getDetails")
#RequestScoped
public class GetDetailsBean {
private String locationID;
public String getLocationID() {
return locationID;
}
public void setLocationID(String locationID) {
this.locationID = locationID;
}
public String addOSDetails(){
return "/app_pages/addOS";
}
}
My second screen which is addOS is
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
>
<h:body>
<h:form>
<h:outputText value="Enter Value" />
<h:inputText value="#{addOS.addValue}"/>
<h:commandButton value="Add OS" action="#{addOS.save}"/>
</h:form>
</h:body>
</html>
I want the LocationID entered in the first screen to be available in this backing bean
#ManagedBean(name="addOS")
#RequestScoped
public class AddOS {
private String addValue;
public String getAddValue() {
return addValue;
}
public void setAddValue(String addValue) {
this.addValue = addValue;
}
public String save(){
return "app_pages/success";
}
}
I donot want values to be set in session.Can be used.
Thoughts and help please
Thanks.
If you really intend to do a forward, as you do in your question, the submitted on the first page data is already there when the second page is rendered: remember, the forward is done within the same HTTP request. So, what you ultimately need is to keep the value for a subsequesnt POST request. You can do it, for example, by storing the information is a hidden field on the second page:
<h:inputHidden value="#{getDetails.locationID}" />
And that's basically it.
If you intend to do a redirect, thus by appending ?faces-redirect=true to a navigation case outcome, you need to store that information in EL flash to be able to retrieve it in the recepient page: there are two requests to be done. So, change your first bean's action method to the following:
public String action() {
...
FacesContext.getCurrentInstance().getExternalContext().getFlash().put("locationID", locationID);
return "result?faces-redirect=true";
}
This way on the recepient page it will be available in flash map, thus by
#{flash.locationID}
in EL scope and
(String)FacesContext.getCurrentInstance().getExternalContext()
.getFlash().get("locationID");
in Java code.
I am trying to achieve functionality where I am generating the tabs in according panel dynamically according to the list.
List is of say some object e.g Person
Now attribute corresponding to each person, I am showing in each tab in a form.
Values are loaded correctly but when I edit those value I am not getting updated values at the backing bean, I am getting only old values.
Can somebody please explain why ?
Here is the code.
Person Object
public class Person {
String name;
//getter setter
#Override
public String toString() {
return name;
}
}
Backing Bean
#ManagedBean(name = "editor")
public class EditorBean {
private List<Person> persons = new ArrayList<Person>();
#PostConstruct
void init() {
persons.add(new Person("dhruv"));
persons.add(new Person("tarun"));
}
public void testAction() {
System.out.println(persons);
}
// Getter Setter*****************//
public List<Person> getPersons() {
return persons;
}
public void setPersons(List<Person> persons) {
this.persons = persons;
}
}
XHTML Code:
<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:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h1>Hello World PrimeFaces</h1>
<h:form>
<p:accordionPanel value="#{editor.persons}" var="person" dynamic="true">
<p:tab title="#{person}">
<p:inputText value="#{person.name}"></p:inputText>
</p:tab>
</p:accordionPanel>
<p:commandButton action="#{editor.testAction()}" value="testAction"></p:commandButton>
</h:form>
</h:body>
</html>
When I run the same with with dynamic="false". This works fine. But in my real scenario I have lots of data which I cannot afford to paint in one go thats why I want to use dynamic = true.
Can somebody explain how to achieve this if not by dynamic = true ??
The reason you're having stale values in your accordion is that dynamic accordions default to cache="true". This attribute causes the accordion to not reload new/updated values. To cause an ajax refresh on tab open, set cache="false" on your accordion