In an application based on jsf 2.1 and Primefaces 6.1.5, I have difficulties implementing a <p:selectCheckboxMenu
I simplified the code according to the instructions here How to create a Minimal, Complete, and Verifiable example
My code now looks quite similar to the code in the Primefaces Showcase.
Primefaces Showcase
After much analyzing, I can describe 'erratic' a bit better. When deselecting an item, the item following it is affected. The last item is not affected at all. And the first item can never be deselected. It seems like a bug in the use of indices.
Can anyone confirm this and perhaps suggest a Workaround?
Here is the xhtml:
<?xml version="1.0" encoding="UTF-8"?>
<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">
<h:form id="form">
<p:panel>
<p:selectCheckboxMenu id="testSCM"
value="#{myForm.testList}"
multiple="true"
label="Choose item..."
updateLabel="true">
<f:selectItems var="s" value="#{myForm.testItems}" itemLabel="#{s}" />
</p:selectCheckboxMenu>
</p:panel>
<p:commandButton value="Submit" update="displayItems" oncomplete="PF('itemDialog').show()" style="margin-top:10px;" />
<p:dialog header="Selected Items" modal="true" showEffect="fade" hideEffect="fade" widgetVar="itemDialog" width="250">
<p:outputPanel id="displayItems">
<p:dataList value="#{myForm.statusList}" var="item" emptyMessage="No items selected">
<f:facet name="header">
Status
</f:facet>
#{item}
</p:dataList>
</p:outputPanel>
</p:dialog>
</h:form>
</ui:composition>
And this is the form:
#Named("myForm")
#SessionScoped
public class MyForm implements Serializable {
private String[] testList;
private List<String> testItems;
public String[] getTestList() {
return testList;
}
public void setTestList(String[] testList) {
this.testList = testList;
}
public List<String> getTestItems() {
return testItems;
}
public void setTestItems(List<String> testItems) {
this.testItems = testItems;
}
public void reset() {
testItems = new ArrayList<>();
testItems.add("Item1");
testItems.add("Item2");
testItems.add("Item3");
testItems.add("Item4");
testItems.add("Item5");
testItems.add("Item6");
}
}
The problem was caused by a bug in Primefaces version 6.1.5. The code works fine when downgrading to Version 6.0 or upgrading to Version 6.1.8, which is what I chose to do.
The problem is described in Primefaces issue tracker on github
Related
I'm using primefaces 5.0 on wildfly 8.2.0 (mojarra 2.2.8).
I tried to use a simple primefaces datatable with expansion but each time I expand a row, my backed bean #PostConstruct is triggered (which reloads the data which nullifies the use of #ViewScoped in the first place).
I've seen other questions on stackoverflow about this problem but no solution worked for me:
I'm using JSF 2.2+
I'm not using any JSTL tags
I disabled partial state saving in web.xml
I tried using different #ViewScoped (bean, view and even omnifaces'one)
My bean:
#Named
#javax.faces.view.ViewScoped
#SuppressWarnings("serial")
public class TestBean implements Serializable {
private List<String> things;
#PostConstruct
public void initialize() {
System.out.println("initializing...");
this.things = Arrays.asList("michael", "david", "paul");
}
public List<String> getThings() {
return this.things;
}
}
My template:
<!DOCTYPE html>
<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>
<title>Test</title>
</h:head>
<h:body>
<p:dataTable value="#{testBean.things}" var="thing">
<p:column>
<p:rowToggler />
</p:column>
<p:column>
<h:outputText value="#{thing}" />
</p:column>
<p:rowExpansion>
<h:outputText value="#{thing}" />
</p:rowExpansion>
</p:dataTable>
</h:body>
</html>
To work, <p:dataTable> has to be inside a <h:form>.
This question already has answers here:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
Closed 5 years ago.
Am a newbie to JSF. Am using JSF 2 and primefaces 4.0 in my application. As stated in the Title, the input value given in the xhtml page, does not set the value to the ManagedBean. I have tried all the possible combination.
growlMessage.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form>
<p:growl id="growl" showDetail="true" sticky="true" />
<p:panel id="panelID" header="Growl">
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="msg" value="Message:" />
<p:inputText id="msg" value="#{growlView.message}" required="true" />
</h:panelGrid>
<p:commandButton value="Save" actionListener="#{growlView.saveMessage}"/>
</p:panel>
</h:form>
</h:body>
</html>
`
GrowlView.java:
import java.io.Serializable;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
#ManagedBean
#ViewScoped
public class GrowlView implements Serializable{
private String message;
public GrowlView() {
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void saveMessage(){
System.out.println("##### hello");
System.out.println("#####"+ getMessage());
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Successful", "Your message: "+message));
context.addMessage(null, new FacesMessage("Second message", "Additional Message details"));
}
}
Do you have a good reason to use JSF 2.0 instead of 2.2? You should use CDI instead of JSF managed beans, which is more or less deprecated. So, use
#Named
#ViewScoped
public class GrowlView implements Serializable
Be sure the ViewScoped annotation is from javax.faces.view. And the beginning of the xhtml should use the new namespace:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui">
Your commandButton should look like this (according to PrimeFaces showcase):
<p:commandButton value="Save" actionListener="#{growlView.saveMessage}" update="growl"/>
Have you tried setting a larger scope to your managed bean, for example #SessionScoped ?
(just for testing purposes). So you could exclude a possible scope problem.
try this following code: using the process and partialSubmit attributes:
<p:commandButton value="Save" actionListener="#{growlView.saveMessage}" update="growl" process="#form" partialSubmit="true"/>
hy,
change for
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form>
<p:growl id="growl" showDetail="true" sticky="true" autoUpdate="true"/>
<p:panel id="panelID" header="Growl">
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="msg" value="Message:" />
<p:inputText id="msg" value="#{pageView.message}" required="true" />
</h:panelGrid>
<p:commandButton value="Save" action="#{pageView.saveMessage}" update="growl"/>
</p:panel>
</h:form>
</h:body>
</html>
and replace
#ManagedBean
with
#ManagedBean(name="pageView")
Versions: PrimeFaces 3.5, JPA 2.1, GlassFish 4.0, Java EE 7, JSF 2.0.
Dialog normally opens and displays data for edition, but the "Update" button in this dialog is not working. Button code follows:
<p:commandButton actionListener="#{funcionarioMB.save}"
value="Alterar"
oncomplete="dlg.hide();"
update=":tblFuncionarios"
ajax="false" />
Full dialog code:
<p:dialog id="dlg"
header="Editar funcionário"
modal="true"
widgetVar="editarDialog"
closable="true"
draggable="false"
appendToBody="true"
maximizable="false"
minimizable="false"
position="center"
resizable="false"
showEffect="slide">
<p:outputPanel>
<h:form id="formAlterar">
<h:panelGrid id="infosFuncionario">
<!-- inputs -->
<p:commandButton actionListener="#{funcionarioMB.save}"
value="Alterar"
oncomplete="dlg.hide();"
update=":tblFuncionarios"
ajax="false" />
</h:panelGrid>
</h:form>
</p:outputPanel>
</p:dialog>
Update commandButton within the dataTable:
<h:form>
<p:commandButton actionListener="#{funcionarioMB.prepareEdit(funcionario.id)}"
value="alterar"
oncomplete="editarDialog.show();"
update=":formAlterar" />
</h:form>
Method save() in the managed bean:
public void save() {
Cargo cargo = this.cargoRepositorio.findById(this.cargoID);
funcionario.setCargo(cargo);
if (this.getFuncionario().getId() == null) {
this.funcionarioRepositorio.add(this.getFuncionario());
} else {
this.funcionarioRepositorio.edit(this.getFuncionario());
}
this.funcionario = new Funcionario();
this.funcionarios = null;
}
Method edit() in the repository:
public void edit(Funcionario funcionario) {
this.manager.merge(funcionario);
}
And the button for updating the entity doesn't work without ajax="false".
where is your datatable ?
just recreate/rebuild your datatable value.
in your managedbean/backing bean add this method after CRUD operation execute
public List<T> refreshDatatable(){
list=yourEJBFacade().getList();
return list
}
in your session bean
public List<T> getList(){
Query q = entityManager.createQuery("select a from YourEntityClass a");
return q.getResultList();
}
update your datatable (update=":tblFuncionarios")
for references see this question at
Primefaces datatable Reset and Reload data
Added ActionEvent actionEvent as save method's parameter and now it's working, thanks to Erick R. Ribeiro's hint in the PrimeFaces Facebook group.
I have p:wizard inside a dialog. When I click on the next button, nothing happens. I've even put h:messages to catch any validation problems. But nothing appears. Here's my code:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<cc:interface>
<cc:attribute name="actionNewComplete" required="false"/>
<cc:attribute name="update" required="false"/>
</cc:interface>
<cc:implementation>
<h:form prependId="false" id="formCreateOffre">
<h:messages showDetail="true"/>
<p:wizard id="wizardOffre" widgetVar="widgetWizardOffre" showNavBar="false" flowListener="#{offreController.handleFlow}">
<p:tab id="tabOffre" title="Offre">
<p:panelGrid styleClass="ui-net-table">
<p:row>
<p:column>
<p:outputLabel value="#{bundle.CreateOffreLabel_participant}" for="participant" />
<p:inputText styleClass="text" style="width: 50px;" id="participant" value="#{offreController.selected.participant}" title="#{bundle.CreateOffreTitle_participant}" />
</p:column>
</p:row>
<p:row>
<p:column>
<p:outputLabel value="#{bundle.CreateOffreLabel_rendezvous}" for="rendezvous" />
<p:calendar styleClass="text" id="rendezvous" value="#{offreController.selected.rendezvous}" disabled="#{offreController.selected.realisation eq null}" title="#{bundle.CreateOffreTitle_rendezvous}">
<p:ajax event="dateSelect" update="delais"/>
</p:calendar>
</p:column>
</p:row>
</p:panelGrid>
</p:tab>
<p:tab id="tabOffreClient" title="Client">
clients
</p:tab>
<p:tab id="tabOffreActivite" title="Activité">
activités
</p:tab>
<p:tab id="tabOffreService" title="Service">
services
</p:tab>
</p:wizard>
<p:commandButton value="Précédent" onclick="widgetWizardOffre.back();" icon="ui-icon-seek-prev"/>
<p:commandButton value="Suivant" onclick="widgetWizardOffre.next();" icon="ui-icon-seek-next" iconPos="right"/>
</h:form>
</cc:implementation>
</html>
Here is the code of the bean.
#ManagedBean(name = "offreController")
#SessionScoped
public class OffreController extends AbstractController<Offre> {
#ManagedProperty(value = "#{navigationController}")
private NavigationController navigation;
#EJB
private app.tfe.netescape.business.OffreFacade ejbFacade;
public OffreController() {
}
public String handleFlow(FlowEvent event) {
return event.getNewStep();
}
The flowListener method is called and returns the next step but nothing happens.
Make sure you have a getter and setter for every bean property you reference in your code. PrimeFaces will fail ungracefully on the wizard step in exactly this manner if it is unable to find both a getter and a setter - even for properties which you are only reading.
Addendum: also, the getters and setters should only do a get and a set of a local value. PrimeFaces doesn't handle other getters and setters well (I cannot explain why this doesn't work, but I've certainly observed it). If you have any additional logic, it should be processed in your listeners.
what version of primefaces did you use?
If is version 5.1 change the event onclick:
onclick="widgetWizardOffre.next();"
by --->
onclick="PF('widgetWizardOffre').next();"
and use same for the event back: onclick="PF('widgetWizardOffre').back();"
Your are already hiding the Navigation bar (next&back buttons), How can the navigation bar work then? Remove showNavBar="false", it's true by default .
I'm using p:tree inside a xhtml which is included dynamically into a tabview of another xhtml. When we change tabs alternatively tree expansion does not work. I'm unable to expand tree by clicking the icon beside the node.
Note: Alternatively it doesn't work. Problem occurs only when dynamic="true" and cache="false" for the tabview in index.xhtml. Complete code is below using which the scenario is easily reproducible.
As I'm using p:tree in many places of my project, I request anybody to provide at least a temporary workaround if this is a bug. I already posted this in primefaces forum. I'm using Primefaces 3.5 with JSF on Tomcat 7.0
index.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<p:tabView dynamic="true" cache="false">
<p:tab title="One">
<ui:include src="/one.xhtml" />
</p:tab>
<p:tab title="two" />
</p:tabView>
</h:body>
</html>
one.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<p:tree widgetVar="treeStructure" value="#{treeBean.root}" var="node" selectionMode="single" id="tree">
<p:treeNode>
<h:outputText value="#{node}" />
</p:treeNode>
</p:tree>
</h:body>
</html>
TreeBean.java
#ManagedBean
#SessionScoped
public class TreeBean {
private TreeNode root;
public TreeNode getRoot() {
return root;
}
public void setRoot(TreeNode root) {
this.root = root;
}
public TreeBean() {
root = new DefaultTreeNode("Root", null);
TreeNode node0 = new DefaultTreeNode("Node 0", root);
TreeNode node00 = new DefaultTreeNode("Node 0.0", node0);
}
}
Found the solution. It's simple and obvious but struggled though. Remove <h:head></h:head> tag in one.xhtml which is not necessary and is reloading the required js files which are already loaded and very much available. Just keep <h:head></h:head> tag in main page always. Here it's index.xhtml.