I have a JSF page with primefaces and I would like to use p:messages for the messages of the input validations and a Growl element for the rest of the things like notifications, errors ...
At the moment I have a Growl with attribute for and I'm sending notifications with this for attribute.
The problem is that I don't know which for attribute I have to put in the p:messages component. If I left it as null the notification messages are showing in Growl and on p:messages.
Here you can see an example of my JSF.
<p:growl id="growlNotifyNewReg" for="growlNotificationsNewRegister"
showSummary="true"
showDetail="true"
autoUpdate="true"/>
<h:outputText value="Validado"/>
<p:selectBooleanCheckbox id="checkValidado" value="#{}" required="true"/>
<h:outputText value="Temperatura (ÂșC)"/>
<p:inputText id="Temperatura" value="#{}" required="true">
<f:validateDoubleRange minimum="-50" maximum="60" />
<f:convertNumber maxFractionDigits="1" />
</p:inputText>
<!-- Other inputs... -->
<p:messages showSummary="true" showDetail="true" redisplay="false"/>
When I want to send a notification I do like this.
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, "summary", "details");
FacesContext.getCurrentInstance().addMessage("growlNotificationsNewRegister", facesMsg);
This code sends messages to Growl component but also to messages component because it doesn't have for attribute. I want to know which attribute I have to put in messages component to show only the validations messages of the form.
As you can see I put redisplay attribute to false. Can I put multiple ids in the for attribute of the p:messages?
Here is an example works as you want, you can change it according to your code :
in .xhtml
<h:form prependId="false">
<p:growl id="growl" for="msg" showDetail="true" sticky="true" />
<p:panel header="Growl">
<h:panelGrid columns="2" cellpadding="5">
<p:outputLabel for="msg" value="Message:" />
<p:inputText id="msg" value="#{growlView.message}" required="true" />
<p:outputLabel for="msg2" value="Message2:" />
<p:inputText id="msg2" value="#{growlView.message2}" required="true" />
</h:panelGrid>
<p:commandButton value="Save" actionListener="#{growlView.saveMessage}" update="growl" />
</p:panel>
<p:messages id="messages" for="msg2" showDetail="true" autoUpdate="true" closable="true" />
</h:form>
in the for attribute for both <p:growl> and <p:messages> you can add whatever Ids you want just like for="id1 id2 .."
in bean
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
#ManagedBean
public class GrowlView {
private String message;
private String message2;
// setters / getters
public void saveMessage() {
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, "summary", "details");
FacesContext.getCurrentInstance().addMessage("msg", facesMsg);
}
}
Related
I have some problems with PrimeFaces 5.2 and client components update mechanism
I created a web page with a button that triggers a server side method. This method update a List of objects and finally
a datatable will be updated with new contents of the List.
<h:form>
...
<p:commandButton value="Add parameters" action="#{adminBean.addParams}"
update=":growl :#{tblSensors.clientId}" />
</h:form>
<h:form>
<p:dataTable id="tblSensors"
var="sensorElem" value="#{adminBean.sensors}"
binding="#{tblSensors}"
>
...
</p:dataTable>
</h:form>
Unfortunatelly when the procedure callback is over, my data table are not updated .. Sincerlly I'm not able to find the problem.
There are no exception in debug phase and I saw nothing in Response data from Firebug.
UPDATE: I saw that when the bean method is called and some variable has been changed; this changes aren't persistent and they are missed every time the method is called
UPDATE 2: as requested, I add the bean code:
#ManagedBean(name="adminBean")
#SessionScoped
public class AdminBean implements Serializable{
private List<Sensor> sensors;
public List<Sensor> getSensors() {
return sensors;
}
public void setSensors(List<Sensor> sensors) {
this.sensors = sensors;
}
//...
#PostConstruct
public void init(){
//...
//initialize sensor list
this.sensors = new ArrayList<Sensor>();
//...
}
//method for adding new sensor
public void addParams(){
try{
//add new sensor element to the list
this.sensors.add(new Sensor(this.param_name,Double.parseDouble(this.min_val),Double.parseDouble(this.max_val),
this.unit, this.selectedChartType, this.selectedFieldType, id_counter++));
}catch(Exception e){
System.out.println("Error "+e.getMessage());
System.out.println("stack "+e.getStackTrace());
}
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,"Successful", "New sensor added!"));
}
//...
}
UPDATE 3: fix some namespace errors.
althouh I'm not familiar with dataTables with data bindings, I think the update-statement is not correct, you need to update the datatable when triggering the commandButton
update=":growl, :tblSensors"
Why not just specify the form id so that updating child elements will be more straightforward? try:
<h:form>
...
<p:commandButton value="Add parameters" action="#{amminBean.addParams}"
update=":growl :datatableform:tblSensors" />
</h:form>
<h:form id="datatableform">
<p:dataTable id="tblSensors"
var="sensorElem" value="#{aminBean.sensors}"
binding="#{tblSensors}">
...
</p:dataTable>
</h:form>
I resolve my issue changing the implementation philosophy: I divide the tab contents in 2 separate xhtml files with related beans, the first one for "parent" element management and the second one for its child elements.
so, the first xhtml:
<h:form>
<p:panel id="panel" header="New Station" style="margin-bottom:10px;">
<h:panelGrid columns="2" cellpadding="5">
<p:inputText id="stationName" required="true" value="#{adminBean.stationName}"/>
<p:inputText id="description" required="true" value="#{adminBean.description}" />
<p:outputLabel value="Station type" for="stationType" />
<p:selectOneMenu id="stationType" value="#{adminBean.selectedStationType}" >
<f:selectItem itemLabel="Select Type" itemValue="-1" noSelectionOption="false" />
<f:selectItems value="#{adminBean.stationType}" />
</p:selectOneMenu>
</h:panelGrid>
</p:panel>
<p:commandButton value="Cancel" action="#{adminBean.cancella}" icon="ui-icon-check" />
<p:commandButton value="Next >" id="nextId" binding="#{nextId}" action="#{adminBean.nextStep}"
icon="ui-icon-check" update=":growl" />
</h:form>
when user selects the Next Button, a new page will be called and its bean will use the bean related with first page in order to retrieve all needed info and show its metadata correctly.
this is the second page:
<h:form>
<p:panel id="panel2" header="Aggiungi sensori" style="margin-bottom:10px;">
<h:panelGrid columns="2" cellpadding="5">
<p:inputText id="param_name" required="true" value="#{adminSensorsBean.param_name}"/>
<p:selectOneMenu id="chartType" value="#{adminSensorsBean.selectedChartType}" >
<f:selectItem itemLabel="Select Type" itemValue="-1" noSelectionOption="false" />
<f:selectItem itemLabel="Line" itemValue="LINE" noSelectionOption="false" />
<f:selectItem itemLabel="Bar" itemValue="BAR" noSelectionOption="false" />
</p:selectOneMenu>
//...
<p:selectOneMenu id="fieldType" binding="#{fieldType}" value="#{adminSensorsBean.selectedFieldType}" >
<f:selectItem itemLabel="Select Field" itemValue="-1" noSelectionOption="false" />
<f:selectItems value="#{adminSensorsBean.fieldsType}" />
</p:selectOneMenu>
</h:panelGrid>
</p:panel>
<p:commandButton value="Add Sensor" id="addSensorId" binding="#{addSensorId}"
action="#{adminSensorsBean.addSensor}"
icon="ui-icon-check" update=":growl :#{tblSensors.clientId}" />
</h:form>
<h:form>
<p:dataTable id="tblSensors"
var="sensorElem"
value="#{adminSensorsBean.sensors}"
scrollable="true"
rowKey="#{sensorElem.id}"
binding="#{tblSensors}"
scrollHeight="150"
>
//...
//this table will be filled with data from form above
//...
</p:dataTable>
</h:form>
//...
<h:form>
<p:commandButton value="Submit" id="submitId" binding="#{submitId}" action="#{adminSensorsBean.saveStation}"
icon="ui-icon-check" update=":growl" />
</h:form>
through the Add Sensor button new information will be inserted into the tableView by the called bean method.
#ManagedBean(name="adminSensorsBean")
#SessionScoped
public class AdminSensorsBean implements Serializable{
//Managed property from bean of first page
#ManagedProperty(value="#{adminBean}")
private AdminBean adminBean;
//...
#PostConstruct
public void init(){
//Here all second page elements as FieldType list, will be initialized using stored information from managed property.
}
//...
}
In this way everything works fine! Honestly I don't known why update event didn't work when I putted all my code in only one jsf page..is it a PrimeFaces/JSF bug? maybe but I don't sure.
Thank you for the support, and sorry for my rough english
In Primefaces, a button will call a prepareCreate method and then open the form dialog. The issue is, this method never get called so that the form in the dialog is not shown.
Command button
<p:commandButton id="createButton1" value="#{bundle.Create}" actionListener="#{purchaseOrderController.prepareCreate}"
update=":PurchaseOrderCreateForm11" oncomplete="PF('PurchaseOrderCreateDialog11').show()"/>
Dialog
<p:dialog id="PurchaseOrderCreateDlg11" widgetVar="PurchaseOrderCreateDialog11" modal="true" resizable="false" appendTo="#(body)" header="#{bundle.CreatePurchaseOrderTitle}">
<h:form id="PurchaseOrderCreateForm11">
<h:panelGroup id="display">
<p:panelGrid columns="2" rendered="#{purchaseOrderController.selected != null}">
<p:outputLabel value="#{bundle.CreatePurchaseOrderLabel_orderNum}" for="orderNum" />
<p:inputText id="orderNum" value="#{purchaseOrderController.selected.orderNum}" title="#{bundle.CreatePurchaseOrderTitle_orderNum}" required="true" requiredMessage="#{bundle.CreatePurchaseOrderRequiredMessage_orderNum}"/>
<p:outputLabel value="#{bundle.CreatePurchaseOrderLabel_quantity}" for="quantity" />
<p:inputText id="quantity" value="#{purchaseOrderController.selected.quantity}" title="#{bundle.CreatePurchaseOrderTitle_quantity}" />
<p:outputLabel value="#{bundle.CreatePurchaseOrderLabel_shippingCost}" for="shippingCost" />
<p:inputText id="shippingCost" value="#{purchaseOrderController.selected.shippingCost}" title="#{bundle.CreatePurchaseOrderTitle_shippingCost}" />
</p:panelGrid>
<p:commandButton actionListener="#{purchaseOrderController.create}" value="#{bundle.Save}" oncomplete="handleSubmit(args,'PurchaseOrderCreateDialog11');"/>
<p:commandButton value="#{bundle.Cancel}" onclick="PurchaseOrderCreateDialog11.hide()"/>
</h:panelGroup>
</h:form>
</p:dialog>
JSF managed bean
#Named("purchaseOrderController")
#SessionScoped
public class PurchaseOrderController implements Serializable {
public PurchaseOrder prepareCreate() {
System.out.println("Purchase order prepare create");
selected = new PurchaseOrder();
initializeEmbeddableKey();
return selected;
}
}
I've got a problem as described in the title.
Small description of the problem is as following:
I have button which is used to open dialog. Then, inside that dialog, there is button which opens another dialog on top of the first one. After clicking second button I want method from controller to be called but nothing happens. Value in h:outputText is read properly, so I guess it is not a problem with connection controller->view.
I'm using:
Spring web 3.1.2.RELEASE
JSF 2.2.10
Primefaces 5.1
Code:
beans.xml
<bean id="testController" class="test.TestController" />
TestController.java
public class TestController implements Serializable
{
private static final long serialVersionUID = 7028608421091861830L;
private String test;
public TestController()
{
test = "abc";
}
public void testMethod()
{
test = "cba";
}
public String getTest()
{
return test;
}
}
test.xhtml
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton value="Basic" type="button" onclick="PF('dlg1').show();" />
</h:panelGrid>
<p:dialog widgetVar="dlg1">
<h:outputText value="Resistance to PrimeFaces is futile!" />
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton value="Basic" type="button" onclick="PF('dlg2').show();" />
</h:panelGrid>
<p:dialog widgetVar="dlg2">
<h:outputText value="#{testController.test}" />
<p:commandButton value="Call method" type="button" actionListener="#{testController.testMethod}" />
</p:dialog>
</p:dialog>
What I tried:
adding appendToBody="true" to each p:dialog
changing from p:commandButton to p:button
changing from actionListener to action
but nothing helps.
I would be grateful for any help or advice of what can be the reason of not calling given method.
There are 3 problems.
You're nesting <p:dialog> components. This doesn't make sense. Separate them.
A <p:dialog> must have its own <h:form>, particularly when you explicitly use appendToBody="true" or appendTo="#(body)", otherwise nothing can be submitted because JavaScript would relocate the dialog out of its position in the HTML DOM tree to the end of body, causing it to not be sitting in a form anymore.
A <p:commandButton type="button"> acts as a "click" button, not as a submit button. Remove that attribute from submit buttons.
All in all, this is how it should look like:
<h:form>
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton value="Basic" type="button" onclick="PF('dlg1').show();" />
</h:panelGrid>
</h:form>
<p:dialog widgetVar="dlg1">
<h:form>
<h:outputText value="Resistance to PrimeFaces is futile!" />
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton value="Basic" type="button" onclick="PF('dlg2').show();" />
</h:panelGrid>
</h:form>
</p:dialog>
<p:dialog widgetVar="dlg2">
<h:form>
<h:outputText value="#{testController.test}" />
<p:commandButton value="Call method" actionListener="#{testController.testMethod}" />
</h:form>
</p:dialog>
OK. I guess I found a way to fix this problem.
It seems that the problem was:
type="button"
I deleted it from the list of attributes of each button and now it works even without h:form. Thanks for help.
I have a bean validation according to:
#Min(value = 0)
#Max(value = 1000000)
private int kilometres;
In my facelet I have:
<p:messages autoUpdate="true" showDetail="true" showSummary="true" />
<p:outputLabel for="kilometres" value="Kilometres" />
<p:inputText id="kilometres" value="#{bean.vehicle.kilometres}">
<p:ajax event="change" />
</p:inputText>
When i have this it works fine, except that all messages for all field ids will be shown. I would like to specify for each field, like this:
<p:messages for="kilometres" autoUpdate="true" showDetail="true" showSummary="true" />
However, when I add the for="kilometres" option, then no validation messages is shown. Have I missed something or is it a bug?
Best regards
Use the <p:message/> component to show validation messages for each input component separately:
<p:outputLabel for="kilometres" value="Kilometres" />
<p:inputText id="kilometres" value="#{bean.vehicle.kilometres}">
<p:ajax/>
</p:inputText>
<p:message for="kilometres"/>
Showcase: AJAX - Validations
UPDATE
In order to show multiple message for a given component (with p:messages) you need to specify the relevant component ID in for="kilometres" and in your backing bean too:
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage("kilometres", new FacesMessage("Message 1"));
context.addMessage("kilometres", new FacesMessage("Message 2"));
In my previous question I had the problem of displaying validation messages from a Login form. That issue is now solved, but this time I am not able to display a custom message with FacesContex#addMessage.
Using JSF + PrimeFaces.
<p:dialog header="Login" widgetVar="loginDlg">
<h:form id="loginForm">
<h:panelGrid columns="3" cellpadding="5">
<h:outputLabel for="username" value="Username:" />
<p:inputText value="#{loginBean.username}" id="username" required="true" label="username" />
<p:message for="username" />
<h:outputLabel for="password" value="Password:" />
<h:inputSecret value="#{loginBean.password}" id="password" required="true" label="password" />
<p:message for="password" />
<f:facet name="footer">
<p:commandButton value="Login" id="loginDlgButton" update=":loginForm,:welcomeMsg" actionListener="#{loginBean.login}"
oncomplete="handleLoginRequest(xhr, status, args)"/>
<p:message for="loginDlgButton" />
</f:facet>
</h:panelGrid>
</h:form>
</p:dialog>
In LoginBean (a SessionScoped ManagedBean):
public void login() {
FacesContext context = FacesContext.getCurrentInstance();
RequestContext rContext = RequestContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
try {
request.login(this.username, this.password);
rContext.addCallbackParam("loggedIn", true);
} catch (ServletException e) {
rContext.addCallbackParam("loggedIn", false);
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Login Error", "Invalid credentials"));
}
}
This code, when validation succeeds and login fails, should display the "Invalid credential" message, but doesn't. Moreover, somewhere in the body of my web page, I have also added this line:
<p:messages autoUpdate="true" />
but my message isn't displayed even there.
Javadocs say that
If clientId is null, this FacesMessage is assumed to not be associated with any specific component instance
But I can't understand what this means.
place <p:messages autoUpdate="true" /> inside your form or inside some wrapper that is being updated by update of your commandButton , or place loginDlgButton instead of null in context.addMessage(...
I don't see a p:messages tag in your code. It is not the same as the p:message tag. p:message is attached to another component and is displayed as part of validation. The p:messages (or p:growl) component is what you are updating in your bean. Try adding a messages or growl component like this:
<h:form id="loginForm">
<p:growl id="messageGrowl" showDetail="true" sticky="false" />
<h:panelGrid columns="3" cellpadding="5">