I have to make autocomplete with multiple selections, all selected items has to be unique. I want to filter already selected values in completeRole function. But completeRole function gets null selectedRoles list. What I am doing wrong? AutoCompleteBean is created new with empty list each time I want to select item in autocomplete input? How can I solve this problem?
AutoCompleteBean.java
package primefaces.beans;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import bpm.beans.entities.Roles;
#ManagedBean(name = "autoCompleteBean")
public class AutoCompleteBean {
private List<Roles> rolesDB;
private List<Roles> selectedRoles;
public AutoCompleteBean() {
rolesDB = RolesBean.getRolesDB();
}
public List<Roles> completeRole(String query) {
List<Roles> suggestions = new ArrayList<Roles>();
List<Roles> rl = getSelectedRoles();
for(Roles p : rolesDB) {
if(p.getTitle().startsWith(query))
if(rl==null){
suggestions.add(p);
}
else if (rl.indexOf(p) < 0)
suggestions.add(p);
}
return suggestions;
}
}
roles.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" xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
</h:head>
<h:body>
<h:form id="form">
<p:autoComplete value="#{autoCompleteBean.selectedRoles}" completeMethod="#{autoCompleteBean.completeRole}"
var="p" itemLabel="#{p.title}" itemValue="#{p}" converter="rolesConverter" multiple="true"
id="autoComplete" >
<p:column style="width:100%">#{p.title}</p:column>
</p:autoComplete>
</h:form>
</h:body>
</html>
to preserve selection across multiple requests, your bean must be at least #ViewScoped.
and you have to process your selection and update your bean instance. add ajax:
<p:autoComplete value="#{autoCompleteBean.selectedRoles}" completeMethod="#{autoCompleteBean.completeRole}"
var="p" itemLabel="#{p.title}" itemValue="#{p}" converter="rolesConverter" multiple="true"
id="autoComplete" >
<p:ajax event="itemSelect" process="#this" update="#this"/>
<p:column style="width:100%">#{p.title}</p:column>
</p:autoComplete>
Related
hi,
i have a problem with my DataTable, when i change the value and try to get it i have the same value before change. Help PLZ i'm with this problem for 8 days.
this is my page 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: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">
<f:view contentType="text/html">
<h:head>
<f:facet name="first">
<meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
<title>PrimeFaces</title>
</f:facet>
</h:head>
<h:body>
<center> <h3> Interventions Préventives </h3> </center>
<h:form id="form">
<p:contextMenu for="cars2" widgetVar="cMenu">
<p:menuitem value="Edit Cell" icon="ui-icon-search" onclick="PF('cellCars').showCellEditor();return false;"/>
<p:menuitem value="Hide Menu" icon="ui-icon-close" onclick="PF('cMenu').hide()"/>
</p:contextMenu>
<p:growl id="msgs" showDetail="true"/>
<p:dataTable id="cars2" var="item" value="#{monTest.personnes}" editable="true" editMode="cell" widgetVar="cellCars">
<f:facet name="header"> Cell Editing with Click and RightClick
</f:facet>
<p:ajax event="cellEdit" listener="#{monTest.onCellEdit}" update=":form:msgs" />
<p:column headerText="Id">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{item.id}" /></f:facet>
<f:facet name="input"><p:inputText id="modelInput" value="#{item.id}" style="width:96%"/></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Year">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{item.nom}" /></f:facet>
<f:facet name="input"><p:inputText value="#{item.nom}" style="width:96%" label="Year"/></f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
</h:form>
</h:body>
</f:view>
</html>
this is my MAnagedBean
package ManagedBeans;
import entities.Personne;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import org.primefaces.event.CellEditEvent;
import session.PersonneFacadeLocal;
#Named(value = "monTest")
#SessionScoped
public class MonTest implements Serializable {
#EJB
private PersonneFacadeLocal personneFacade;
private List<Personne> personnes;
private String value1;
#PostConstruct
public void init(){
personnes=personneFacade.findAll();
}
public MonTest() {
}
public List<Personne> getPersonnes() {
personnes=personneFacade.findAll();
return personnes;
}
public void test(Personne p){
System.out.println("*************************************************************************");
System.out.println(p.getNom()+"**************"+p.getPrenom()+"*********************"+p.getAge());
}
public PersonneFacadeLocal getPersonneFacade() {
return personneFacade;
}
public void setPersonneFacade(PersonneFacadeLocal personneFacade) {
this.personneFacade = personneFacade;
}
public String getValue1() {
return value1;
}
public void setValue1(String value1) {
this.value1 = value1;
}
public void onCellEdit(CellEditEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
if(newValue != null && !newValue.equals(oldValue)) {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Cell Changed", "Old: " + oldValue + ", New:" + newValue);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
}
Your getter to the list personnes is retrieving the data from the database and your onCellEdit method is not updating the database. So the data on the datatable will always be the same.
Change your onCellEdit method to trigger the update method to the entity which is being changed (to get this entity, use event.getObject()).
The setter method of selectedRestaurant is called but the menu just flips back and doesn't render the <h:outputText>. The Menu has content, so the List used in <f:selectItems> is not empty. As I am using omnifaces.SelectItemsConverter I suppose it is not due to a conversion problem.
This is my 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:head />
<h:body>
<h:panelGroup id="adminOneMenu" layout="block">
<h:form>
<p:selectOneMenu value="#{bugBean.selectedRestaurant}" converter="omnifaces.SelectItemsConverter">
<f:selectItem itemValue="" itemLabel="Restaurant wählen"/>
<f:selectItems value="#{bugBean.restaurants('London')}" var="restaurant" itemLabel="#{restaurant.screenName}"/>
<p:ajax update=":adminOneMenu"/>
</p:selectOneMenu>
<h:outputText value="#{bugBean.selectedRestaurant.screenName}" />
</h:form>
</h:panelGroup>
</h:body>
</html>
This is the backing bean:
package huhu.main.managebean;
import java.io.Serializable;
import java.util.List;
import javax.ejb.EJB;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import huhu.model.generated.Restaurant;
import huhu.service.RestaurantService;
#Named
#SessionScoped
public class BugBean implements Serializable {
private static final long serialVersionUID = 1L;
private Restaurant selectedRestaurant;
#EJB
RestaurantService rs;
public List<Restaurant> getRestaurants(String city){
List<Restaurant> restaurants;
restaurants = rs.getRestaurantsInCity(city);
return restaurants;
}
public Restaurant getSelectedRestaurant() {
return selectedRestaurant;
}
public void setSelectedRestaurant(Restaurant selectedRestaurant) {
this.selectedRestaurant = selectedRestaurant;
}
}
If there would be a conversion error, you should get an error message.
Did you implement #equals() and #hashcode() in class Restaurant?
How can i pass an object to the action method of an commandButton? I use a datatable which is the basis of a composite component. The composite component should provide the possibility to exchange the buttons which are added to the rows of the datatable. I thought i can realize this with facets, but i have problems passing objects from the datatables list to action methods, neither directly via an EL nor via an property action listener.
View:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:customer="http://java.sun.com/jsf/composite/components/customer">
<ui:composition template="/WEB-INF/templates/template.xhtml">
<ui:define name="content">
<h:form id="customerList">
<customer:list list="#{customerControllerBean.list}">
<f:facet name="rowButton">
<h:commandButton value="#{msg.deleteButtonLabel}"
action="#{customerControllerBean.delete(customer)}" />
<h:commandButton value="#{msg.deleteButtonLabel}" action="#{customerControllerBean.deleteCustomer}">
<f:setPropertyActionListener target="#{customerControllerBean.customer}" value="#{customer}"/>
</h:commandButton>
<h:button outcome="customerdetail.jsf?id=#{customer.id}"
value="#{msg.editButtonLabel}" />
</f:facet>
</customer:list>
</h:form>
</ui:define>
</ui:composition>
</html>
Using the following composite component customer:list:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface>
<composite:attribute name="list" />
<composite:facet name="rowButton" />
</composite:interface>
<composite:implementation>
<p:dataTable id="customer" var="customer" value="#{cc.attrs.list}">
...
<p:column>
<composite:renderFacet name="rowButton" />
</p:column>
</p:dataTable>
</composite:implementation>
</html>
The backing bean:
#Named
#ConversationScoped
public class CustomerControllerBean implements Serializable {
private static final long serialVersionUID = 6168621124401208753L;
List<Customer> allCustomers = null;
private Customer customer;
// setters and getters ...
#PostConstruct
public void loadAllCustomers() {
// load customers
}
public List<Customer> getList() {
return allCustomers;
}
public String delete(Customer customer) {
// delete customer...
return "deleted";
}
public String deleteCustomer() {
// delete customer...
return "deleted";
}
Is it not possible to pass objects to methods in this context?
Since you're using Primefaces you could take advantage of the its datatable features like its properties and events to set your model.
Using Primefaces' DataTable features
In your controller you may specify the model and the operations to be performed on it, in this case I used an EJB as example.
#ManagedBean
#ViewScoped
public class CustomerBean
{
private Customer model;
#EJB
private CustomerService cs;
public void rowSelected()
{
// log or do stuff
}
public void delete()
{
cs.delete(model);
}
// getters & setters
}
Then you specify the selectionMode and the selection properties in your datatable, with the selection being mapped to your model.
<p:dataTable id="dtModel" var="row" value="#{bean.list}" selectionMode="single" selection="#{bean.model}">
<p:ajax event="rowSelect" process="#this" listener="#{bean.rowSelected}" update=":content" />
</p:datatable>
In this case I used a listener in the p:ajax tag but it is only an example that may be useful if you want to do something with your model once it is selected, but it is not required to set your model. Your model will be set using the bean's setter method.
Passing row as parameter
In your controller you specify the method that receives the model as parameter.
#ManagedBean
#ViewScoped
public class CustomerBean
{
#EJB
private CustomerService cs;
public void delete(Customer candidate)
{
cs.delete(candidate);
}
// getters & setters
}
And in your datatable you use the row object as specified in var property.
<p:dataTable id="dtModel" var="row" value="#{bean.list}">
<p:column headerText="name">
<h:outputText value="#{row.name}" />
</p:column>
<p:column headerText="delete">
<p:commandButton value="delete" actionListener="#{bean.delete(row)}" />
</p:column>
</p:datatable>
I prefer to use the first example as it allows you to set the model by selecting a row and then performing various operations on it, like delete, edit or view its details. You could enable or disable buttons on your UI by checking if the model is selected or not, etc...
Hint
Instead of Composite Components you could use simple Facelets templates to create a simple taglib. They usually work fine, the only downside is that you cannot enforce an interface to the use of these components.
You may also check the PrimeFaces showcase, which has a lot of useful examples.
I hope it helps.
I am new with Primefaces and I try to use a treeTable from Primefaces 3.3.1.
Only the first record of the TreeTable is shown at the beginning. Then, when I click on the little image to expand the TreeTable, nothing happens. In FireBug, I can se the following result:
<partial-response>
<error>
<error-name>class java.lang.StringIndexOutOfBoundException</error-name>
<error-message>String index out of range: -1</error-message>
</error>
</partial-response>
If I force my treeTable to be expanded with node0.setExpanded(true), then the TreeTable is expanded. Then I can collapse it but again, I am no more able to expand it.
In other posts, it is written that the model and/or the bean must implements Serializable. I try but it does not work.
Below, my model (what will be placed in each record of the TreeTable):
public class MyModel{
private String field_1;
private String field_2;
public MyModel(){};
public MyModel(String field_1, String field_2){
this.field_1 = field_1;
this.field_2 = field_2;
}
//Getters and setters
}
Below, the JSF Managed bean that create the TreeTable:
#ManagedBean
#SessionScoped
public class MyManagedBean{
public TreeNode root;
}
public MyManagedBean{
root = new DefaultTreeNode("root",null);
TreeNode node0 = new DefaultTreeNode(new MyModel("Field 1", "Field 2"), root);
TreeNode sub0 = new DefaultTreeNode(new MyModel("Sub", "Sub"), node0);
//node0.setExpanded(true);
}
public TreeNode getRoot(){
return root;
}
Finally, my JSF file:
<!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: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">
<f:view contentType="text/html">
<h:head>
<f:facet name="first">
<meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
<title>PrimeFaces</title>
</f:facet>
</h:head>
<h:body>
<p:treeTable value="#{myManagedBean.root}" var="test">
<p:column>
<f:facet name="header">
Field 1
</f:facet>
<h:outputText value="#{test.field_1}" />
</p:column>
<p:column>
<f:facet name="header">
Field 2
</f:facet>
<h:outputText value="#{test.field_2}" />
</p:column>
</p:treeTable>
</h:body>
</f:view>
Thank you in advance for your help!
Solved it. I forgot to wrap the treeTable in an h:form tag. It works fine now.
I'm trying to make a partial rendering navigation for an application. The code bellow is a concept test that works well with exception of the commandbutton on x.xhtml file. It does't fire the actionListeneron a click. This is used to change the url for the included part.
index.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: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">
<f:view contentType="text/html">
<h:head>
<f:facet name="first">
<meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
<title>PrimeFaces</title>
</f:facet>
<style type="text/css">
.ui-layout-north {
z-index:20 !important;
overflow:visible !important;;
}
.ui-layout-north .ui-layout-unit-content {
overflow:visible !important;
}
</style>
</h:head>
<h:body>
<p:layout fullPage="true">
<p:layoutUnit position="north" size="100" header="Top" resizable="true" closable="true" collapsible="true">
<h:form>
<p:menubar>
<p:submenu label="File" icon="ui-icon-document">
<p:menuitem value="XXX" update=":wrapper" actionListener="#{tbean.doNav}">
<f:attribute name="xxx_page" value="x.xhtml" />
</p:menuitem>
<p:menuitem value="YYY" update=":wrapper" actionListener="#{tbean.doNav}">
<f:attribute name="xxx_page" value="y.xhtml" />
</p:menuitem>
</p:submenu>
</p:menubar>
</h:form>
</p:layoutUnit>
<p:layoutUnit position="center">
<p:outputPanel id="wrapper">
<ui:include src="#{tbean.url}"/>
</p:outputPanel>
</p:layoutUnit>
</p:layout>
</h:body>
</f:view>
</html>
x.xhtml
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<ui:component 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"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:form>
<p:commandButton value="zzz" update=":wrapper" actionListener="#{tbean.doNav}">
<f:attribute name="xxx_page" value="z.xhtml" />
</p:commandButton>
<p:dataTable var="car" value="#{tbean.cars}">
<p:column>
<f:facet name="header">
Name
</f:facet>
<h:outputText value="#{car.name}" />
</p:column>
</p:dataTable>
</h:form>
</ui:component>
y.xhtml
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<ui:component 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"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:outputText value="yyy"/>
</ui:component>
z.xhtml
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<ui:component 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"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:outputText value="zzz"/>
</ui:component>
tbean.java
package com.teste;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.event.ActionEvent;
#ManagedBean
#RequestScoped
public class tbean {
private String url = "y.xhtml";
private List<Car> cars = new ArrayList<>();
public tbean() {
for (int i = 0; i < 10; i++) {
cars.add(new Car(i));
}
}
public void setUrl(String url) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "setUrl :{0}", this.url);
this.url = url;
}
public String getUrl() {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "getUrl :{0}", this.url);
return this.url;
}
public void doNav(ActionEvent event) {
this.url = (String) event.getComponent().getAttributes().get("xxx_page");
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "doNav :{0}", this.url);
}
public List<Car> getCars() {
return cars;
}
}
Your backing bean is request scoped. This means that it's created on every HTTP request. So the url property will default to y.xhtml on every request.
Submitting the form by the command button creates a new HTTP request. So it gets a new instance of the request scoped bean with the url property defaulted to y.xhtml. When JSF needs to process the form submit, it can't figure the button pressed because it's not present in y.xhtml. So JSF cannot invoke the action associated with the button pressed.
Placing the bean in view scope should fix your problem.
#ManagedBean
#ViewScoped
public class tbean {
This will remember the url property properly across the HTTP requests on the very same view (by returning null or void on every action).
See also:
How to choose the right bean scope?
As to the whole design, you need to make absolutely sure that all the ajax actions are been invoked by PrimeFaces components, not by the standard JSF <f:ajax> ones, otherwise the commandbutton would still not be invoked due to a bug in JSF JS.
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated (point 7)