I've been reading and searching among the many pages with similar questions, but I cannot find why my commandButton is not invoking the action (I have debugged it and that is the problem). My code looks simple but... doesn't work. Maybe it's a newbie problem, but I don't know where it is.
I'm writing a portlet for liferay using JSF2 and Liferay Faces Alloy.
I've also read the question commandLink/commandButton/ajax backing bean action/listener method not invoked, very educational for me, but none of the points have solved my problem.
Here is my mainView.xhtml file:
<?xml version="1.0"?>
<f:view
xmlns="http://www.w3.org/1999/xhtml"
xmlns:aui="http://liferay.com/faces/aui"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head />
<h:body>
<h:form>
<h:messages globalOnly="true" layout="table" />
<h:outputText id="esteTexto" value="#{ramSession.texto}" />
<br />
<h:commandButton action="#{ramSession.add}" styleClass="btn btn-default" value="#{ramSession.texto}">
</h:commandButton>
</h:form>
</h:body>
</f:view>
And here is my SessionScoped ManagedBean file, RamSession.java:
#ManagedBean
#SessionScoped
public class RamSession extends AbstractBaseBean implements Serializable {
private static final long serialVersionUID = 919724848720360000L;
private String texto;
public void add() {
this.texto = new String("Entrando");
}
#PostConstruct
public void postConstruct() {
this.texto = new String("Jereje");
}
public String getTexto() {
logger.info("gettingTexto");
addGlobalSuccessInfoMessage();
return this.texto;
}
public void setTexto(String texto) {
this.texto = texto;
}
}
I have also tried returning a String (even not necessary), with an actionListener method and even with ajax but nothing. Can anybody help me? Thanks a lot.
Maybe your mojarra listner is not configured correctly.
Follow one of the two following sub-steps
a. Add the liferay-faces-init.jar dependency in each Liferay JSF project by adding the following code to each pom.xml :
<dependency>
<groupId>com.liferay.faces</groupId>
<artifactId>liferay-faces-init</artifactId>
<version>3.1.3-ga4</version>
</dependency>
b. Add the following code in each WEB-INF/web.xml of all your JSF projects :
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
Why not initialize texto in the declaration?
private String texto = "Jereje";
public void addGlobalSuccessInfoMessage(){
//faces message
}
//Getter Setter
Then you can remove the entire PostConstruct method.
Also if all you want to do is set a string and update without navigation just use f:setPropertyActionListener with a f:ajax for updating your messages. You can use action if you want by returning null or void, or actionListener and set the string inside of that, but I'm not seeing why you'd want to. This link may help with those options... Answer by Balus C.
May want to remove any extra logic from your getter method as well. This won't affect your problem but it's cleaner and creating a success message on a getter seems problematic.
<h:form id="myForm">
<h:messages globalOnly="true" layout="table" />
<h:outputText id="esteTexto" value="#{ramSession.texto}" />
<br />
<h:commandButton value="#{ramSession.texto}" actionListener="#{ramSession.addGlobalSuccessInfoMessage()}" styleClass="btn btn-default">
<f:setPropertyActionListener value="Entrando" target="#{ramSession.texto}" />
<f:ajax render="myForm" />
</h:commandButton>
</h:form>
Related
Primefaces 4.0
I need to reset the initial disable-state of components contained in a p:dialog.
The following simplified example shows the problem:
XTML:
<p:dialog header="header" widgetVar="dialog" appendTo="#(body)"
modal="true" resizable="false">
<h:form id="form">
<p:inputText value="#{bean.text}" id="text" />
<p:commandButton value="Disable InputText"
action="#{bean.disableInputText}" />
<p:commandButton value="Cancel"
action="#{bean.cancelDialog}"
process="#this"
update="#form" immediate="true">
<p:resetInput target="#form"/>
</p:commandButton>
</h:form>
</p:dialog>
ManagedBean:
#ViewScoped
public class Bean {
public void disableText() {
final FacesContext context = FacesContext.getCurrentInstance();
final UIViewRoot root = context.getViewRoot();
final UIComponent component = root.findComponent(":text");
if (uiComponent instanceof InputText) {
((InputText) uiComponent).setDisabled(true);
}
}
public void cancel() {
// reset disable-state of the disable-state of all components in a generic way.
}
}
While using the dialog the p:inputText element can be disabled. If the dialog was canceled and opened again, inputText should not disabled. The initial state should have been restored. Please note that this example is simplified and i am looking for a general solution that also works with a formular with 10+ input elements.
The general (and broadest) solution
For a general solution you can use the state saving functionality that is available in Java Server Faces. Using your code example as a base (with some minor changes to clean things up), here is an example that uses state saving and restores the previous state of the component;
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Disable Test</title>
</h:head>
<h:body>
<p:dialog header="header" widgetVar="dialog" appendTo="#(body)" modal="true" resizable="false">
<h:form id="form">
<p:inputText value="#{disableTestBean.text}" id="text"/>
<p:commandButton value="Disable InputText" action="#{disableTestBean.onDisable}" update="#form" />
<p:commandButton value="Cancel" action="#{disableTestBean.onCancel}" update="#form" onsuccess="PF('dialog').hide()" />
</h:form>
</p:dialog>
<button onclick="PF('dialog').show()">Open</button>
</h:body>
</html>
To actually see the reset happening, get rid of the onsuccess attribute from the second commandButton - as it currently closes the dialog.
#Data
#Named
#ViewScoped
public class DisableTestBean implements Serializable {
private String text;
private Object prevState;
private UIComponent findComponent(String where) {
final FacesContext context = FacesContext.getCurrentInstance();
final UIViewRoot root = context.getViewRoot();
return (UIComponent) root.findComponent(where);
}
public void onDisable() {
final InputText component = (InputText) findComponent(":form:text");
component.setDisabled(false);
component.setValue("");
prevState = component.saveState(FacesContext.getCurrentInstance());
component.setValue("meh");
component.setDisabled(true);
}
public void onCancel() throws IOException {
final InputText component = (InputText) findComponent(":form:text");
component.restoreState(FacesContext.getCurrentInstance(), prevState);
}
}
The example targets one specific input component. However, if you need to handle multiple components, you can easily use a loop to accomplish what you want in a general way.
As a demonstration I not only reset the disabled state in the backing bean above, but also the value (content) of the input component. This demonstrates you how you can actually reset the complete state of the component (not only a single attribute or value). So the solution is broad and very general.
The second more direct approach
The second approach is to do what #Kukeltje is hinting at in his comments above. Use the disabled= attribute on the input components and have a backing bean value that just changes the value to false when you press Cancel. This is not as general and wont work for everything else, but it will do the job in your particular use case. If you are only interested in the disabled state it's probably even the prefered way of doing it. If you want an example of that as well, I can extend this answer - just let me know.
i want to pass GET parameter from URL to a method, that called by clicking on button.
For example i have URL: /someurl/semepage.xhtml?id=1. And i have a button on my page:
<p:commandButton value="say it" action="#{test.sayIt(param['id'])}"/>
The bean looks like:
#ManagedBean
#ViewScoped
public class Test{
public void sayIt(String value){
System.out.println(value);
}
}
But when i am clicking on button, its just not react. Why is this happen ? Method even not called.
If i pass arguments staticaly like here:
<p:commandButton value="say it" action="#{test.sayIt('someword')}"/>
everything is ok.
Here is one way - using the <f:param, like this:
<h:commandButton value="Test The Magic Word" action="#{test.sayIt}">
<f:param name="id" value="#{param['id']}"></f:param>
<f:ajax execute="something" render="something_else"></f:ajax>
</h:commandButton>
And in your bean
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext()
.getRequest();
String id = request.getParameter("id");
#Daniel's response is OK, but here it goes a simpler JSF 2-ish alternative for your case, using <f:viewParam /> and EL parameter passing. Note the <f:ajax /> is not needed in this case, as <p:commandButton /> has ajax behaviour by default.
<html xmlns="http://www.w3.org/1999/xhtml"
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:body>
<f:metadata>
<f:viewParam name="id" />
</f:metadata>
<h:form>
<p:commandButton value="say it" action="#{bean.sayIt(id)}" />
</h:form>
</h:body>
</html>
#ManagedBean
#ViewScoped
public class Bean implements Serializable {
public void sayIt(String value) {
System.out.println(value);
}
}
Tested with JSF 2.2.5 and Primefaces 4. Remember changing tag namespaces in case of using JSF 2.1.x.
Just for the fun of it, have you tried request.getParameter('id')?
This question already has answers here:
How to dynamically add JSF components
(3 answers)
Closed 6 years ago.
A click on a commandButton should trigger an action in a ManagedBean: to add a new "outputText" component to the current page.
The overall idea is to have the page changed dynamically with user action, with server side action because new elements added to the page need data from a db to be laid out.
-> How do I add a component to the page from a managed bean in jsf / primefaces? Let's say that the elements should be added in an existing div like:
<div id="placeHolder">
</div>
(this div could be changed to a jsf panel if needs be)
Note: if alternative methods are better to achieve the same effect I'd be glad to learn about them.
I'll provide you another solution apart from the one you posted. Basically it has a List of given outputs, which is increased everytime the button is pushed. That should render exactly the same DOM tree as the solution you stated:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Tiles</title>
<h:outputStylesheet name="css/320andup_cle.css" />
</h:head>
<h:body>
<h:form>
<h:commandButton actionListener="#{bean.createNewTile}" title="new"
value="new" />
</h:form>
<h:panelGroup layout="block" id="tiles">
<ui:repeat var="str" value="#{bean.strings}">
<h:panelGroup>
<h:outputText styleClass="tile" value="#{str}" />
</h:panelGroup>
</ui:repeat>
</h:panelGroup>
</h:body>
</html>
#ManagedBean
#SessionScoped
public class Bean {
List<String> strings = new ArrayList<String>();
public List<String> getStrings() {
return strings;
}
public void createNewTile() {
strings.add("output");
}
}
Apart from being much simpler IMHO, it has a main advantage: it doesn't couple your server side code to JSF implicit API. You can change the #ManagedBean annotation for #Named if you want it to be a CDI managed bean.
The solution:
This is a jsf page with a button creating a new div each time it is clicked:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Tiles</title>
<h:outputStylesheet name="css/320andup_cle.css" />
</h:head>
<h:body>
<h:form>
<h:commandButton actionListener="#{bean.createNewTile()}" title="new" value="new"/>
</h:form>
<h:panelGroup layout="block" id="tiles">
</h:panelGroup>
</h:body>
</html>
The Managed Bean:
#Named
#SessionScoped
public class Bean implements Serializable {
private UIComponent found;
public void createNewTile() {
HtmlPanelGroup div = new HtmlPanelGroup();
div.setLayout("block");
HtmlOutputText tile = new HtmlOutputText();
tile.setValue("heeeeeRRRRRRRRRRRRRR ");
tile.setStyleClass("tile");
div.getChildren().add(tile);
doFind(FacesContext.getCurrentInstance(), "tiles");
found.getChildren().add(div);
}
private void doFind(FacesContext context, String clientId) {
FacesContext.getCurrentInstance().getViewRoot().invokeOnComponent(context, clientId, new ContextCallback() {
#Override
public void invokeContextCallback(FacesContext context,
UIComponent component) {
found = component;
}
});
}
}
See this app built with this logic of dynamically generated components: https://github.com/seinecle/Tiles
I'm new to JSF and trying to understand how include and param work, but have been stuck. Any help is much appreciated.
I have 2 simple pages (for testing purpose), Page1.xhtml and Page2.xhtml. I want to include Page2 into Page1 with one parameter using and in Page1. When I call Page2 directly, I can see the parameter being passed properly, but when I call Page1, Page2 is being included without the parameter. Below is the code.
Page1:
<h:body>
<h:form id="test">
<b>Page 1</b><br/>
<ui:include src="Page2.xhtml">
<ui:param name="id" value="123" />
</ui:include>
<b>End of Page 1</b>
</h:form>
Page2:
<h:head>
<f:view contentType="text/html"></f:view>
</h:head>
<h:body>
<h:form>
<h:outputLabel for="ID" value="ID on Page2: "/>
<h:outputText id="ID" value="#{pageTestBean.id}"/>
</h:form>
</h:body>
</html>
PageTestBean:
#ManagedBean
#SessionScoped
public class PageTestBean {
private Long id=new Long(11111);
public void init() {
//doesn't do anything yet;
}
// Getters and Setters
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
I'm expecting to see "123" as the output Id on Page1, not "11111" which is the default value when no parameter is passed in. However, I always see 11111. Is my expectation wrong?
First of all, your include is handled inappropriately: the incuded page should be composed solely of <ui:composition> like the following one:
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets">
...incuded page content...
</ui:composition>
An excellent point of reference is BalusC's answer to How to include another XHTML in XHTML using JSF 2.0 Facelets?.
Next, the included parameter is to be accessed simply via #{paramName} in the included page, like in:
<h:outputText value="#{paramName}" />
Parameter name is id in your case.
There are some other drawbacks of your code, like abusing session scope and nested HTML forms, but that's another question. The last but not the least is the thing that you have to understand how to deal with managed beans in views.
I have an h:inputText and an h:message connected to it:
<h:inputText id="myText" value="#{myController.myText}" />
<a4j:outputPanel>
<h:message for="myText" .../>
</a4j:outputPanel>
I want to send a message to it from java, in a manner like:
FacesContext.getCurrentInstance().addMessage(arg0, arg1);
which is sent to h:messages, but to a specific id in a specific form.
How can I do this? (Without implementing validation bean or validation method - meaning without throwing validation exception).
You need to provide the so called client id, which you'll find on UIComponent.
The following is a quick example of how to use this.
Consider the following bean:
#ManagedBean
#RequestScoped
public class ComponentMsgBean {
private UIComponent component;
public UIComponent getComponent() {
return component;
}
public void setComponent(UIComponent component) {
this.component = component;
}
public String doAction() {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(component.getClientId(), new FacesMessage("Test msg"));
return "";
}
}
being used on the following Facelet:
<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"
>
<h:body>
<h:form>
<h:outputText id="test" value="test component" binding="#{componentMsgBean.component}"/>
<h:message for="test"/>
<h:commandButton value="click me" action="#{componentMsgBean.doAction}" />
</h:form>
</h:body>
</html>
This will add a Faces message with content "Test msg" for the outputText component used in the example.
Another way to do that is: give an ID to the form, like "form1", then, when add the message, the clientId is "form1:test".