Datatable of primefaces not editable inside of a form - primefaces

Hy,
When I have a datatable of primefaces with paginator and its only readable and not editable, its not needed to be inside of a form, right? although I have seen it many times inside of it
Thanks

You understand correctly. JSF forms use the "post-back" technique to submit form data back to the page that contains the form. If you do not want to do that, you do not have h:form.
The example show below.
xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!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:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Setting Default selectOneMenu</title>
</h:head>
<h:body>
<p:dataTable var="car"
value="#{dtBasicView.cars}"
rows="5"
paginator="true"
paginatorTemplate="{CurrentPageReport}
{FirstPageLink} {PreviousPageLink}
{PageLinks}
{NextPageLink}
{LastPageLink}
{RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15">
<p:column headerText="Id">
<h:outputText value="#{car.id}" />
</p:column>
<p:column headerText="Year">
<h:outputText value="#{car.year}" />
</p:column>
<p:column headerText="Brand">
<h:outputText value="#{car.brand}" />
</p:column>
<p:column headerText="Color">
<h:outputText value="#{car.color}" />
</p:column>
</p:dataTable>
</h:body>
</html>
managedbean
#ManagedBean(name="dtBasicView")
#ViewScoped
public class BasicView implements Serializable {
private List<Car> cars;
#ManagedProperty("#{carService}")
private CarService service;
#PostConstruct
public void init() {
cars = service.createCars(10);
}
public List<Car> getCars() {
return cars;
}
public void setService(CarService service) {
this.service = service;
}
}

Related

JSF Datatable - how to select row on button push in row

I would like a button in a Primefaces DataTable row to show a dialog showing more information about the object in the row. When I click anywhere in the row not in the button, the row is selected. However, when I press the button, the row is not selected. How may I make the row that the button is in the selected row?
This example from the Primefaces showcase sets selectedCar in the backing bean and displays a dialog containing data from the row on clicking a button in the row but leaves the row unselected:
<p:dataTable id="basicDT" var="car" value="#{dtSelectionView.cars1}">
<f:facet name="header">
Basic
</f:facet>
<p:column headerText="Id">
<h:outputText value="#{car.id}" />
</p:column>
<p:column headerText="Year">
<h:outputText value="#{car.year}" />
</p:column>
<p:column headerText="Brand">
<h:outputText value="#{car.brand}" />
</p:column>
<p:column headerText="Color">
<h:outputText value="#{car.color}" />
</p:column>
<p:column style="width:32px;text-align: center">
<p:commandButton update=":form:carDetail" oncomplete="PF('carDialog').show()" icon="ui-icon-search" title="View">
<f:setPropertyActionListener value="#{car}" target="#{dtSelectionView.selectedCar}" />
</p:commandButton>
</p:column>
</p:dataTable>
.. and this example from the same page selects a row in the table and the backing bean but an subsequent button click to display a dialog:
<p:dataTable id="singleDT" var="car" value="#{dtSelectionView.cars2}" selectionMode="single" selection="#{dtSelectionView.selectedCar}" rowKey="#{car.id}">
<f:facet name="header">
Single with Row Click
</f:facet>
<p:column headerText="Id">
<h:outputText value="#{car.id}" />
</p:column>
<p:column headerText="Year">
<h:outputText value="#{car.year}" />
</p:column>
<p:column headerText="Brand">
<h:outputText value="#{car.brand}" />
</p:column>
<p:column headerText="Color">
<h:outputText value="#{car.color}" />
</p:column>
<f:facet name="footer">
<p:commandButton process="singleDT" update=":form:carDetail" icon="ui-icon-search" value="View" oncomplete="PF('carDialog').show()" />
</f:facet>
</p:dataTable>
I'm looking for a graceful solution where you can click any of multiple buttons in a row and select the row at the same time. Here's a use case where multiple buttons are useful - the data for the row contains two richtext fields of arbitrary size which are not easily shown in the table:
Use the var value of the primefaces dataTable attribute, to create a commandLink (or button) inside each row of the dataTable:
If the commandLink is clicked, an actionListener is invoked and sets the rows object as the selectedElement inside the dataTableDialog bean.
Once the ajax request as finished successfully, the update attribute of the commandLink forces the dialog to request the current data from the bean.
Now the JavaScript code of the oncomplete attribute shows up the dialog.
Take a look at the actionListener of the commandLink.
The rows object is stored inside member variable selectedElement. The data of this selected element is shown by the dialog.
Here you've got a nearly complete example:
<h:form id="form">
<p:dialog widgetVar="dlg" modal="true" id="dialog">
<h:outputText value="#{dataTableDialog.selectedElement.key} / #{dataTableDialog.selectedElement.val}" />
</p:dialog>
<p:dataTable
var="cur"
tableStyle="width: auto !important;"
value="#{dataTableDialog.elements}">
<p:column>
<h:outputText value="#{cur.key}" />
</p:column>
<p:column>
<h:outputText value="#{cur.val}" />
</p:column>
<p:column>
<p:commandLink
value="Read more ..."
actionListener="#{dataTableDialog.setSelectedElement(cur)}"
update="form:dialog"
oncomplete="PF('dlg').show()" />
</p:column>
</p:dataTable>
</h:form>
The bean:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
#javax.inject.Named
#javax.enterprise.context.SessionScoped
public class DataTableDialog implements Serializable {
private List<Data> elements;
private Data selectedElement;
#PostConstruct
public void init() {
elements = new ArrayList<>();
elements.add(new Data("Elem 1 Key", "Elem 1 Value"));
elements.add(new Data("Elem 2 Key", "Elem 2 Value"));
}
public List<Data> getElements() {
return elements;
}
public Data getSelectedElement() {
return selectedElement;
}
public void setSelectedElement(Data selectedElement) {
this.selectedElement = selectedElement;
}
}
The data class:
public class Data implements Serializable {
private String key, val; // +getter/+setter
public Data(String key, String value) {
this.key = key;
this.value = value;
}
}
Inspired by the primefaces show case for dataTable Selection:
if it is an option to ommit the button, this example opens a dialog on row click, including row selection.
add an ID to your DataModel
add the attributes selection, selectionMode and rowKey to the dataTable
insert <p:ajax ... /> tag inside dataTable to show the dialog on rowSelectEvent
The facelet:
<!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 id="form">
<p:dialog
widgetVar="elementDialog" modal="true">
<p:outputPanel id="elementDetail">
<p:panelGrid
columns="2"
rendered="#{not empty bean.selectedElement}"
columnClasses="label,value">
<h:outputText value="Key: #{bean.selectedElement.key}" />
<h:outputText value="Val: #{bean.selectedElement.val}" />
</p:panelGrid>
</p:outputPanel>
</p:dialog>
<p:dataTable
var="element"
value="#{bean.elements}"
selection="#{bean.selectedElement}"
selectionMode="single"
rowKey="#{element.id}"
tableStyle="width: auto !important;">
<p:ajax event="rowSelect" oncomplete="PF('elementDialog').show();" />
<p:column headerText="Key">#{element.key}"</p:column>
<p:column headerText="Val">#{element.val}"</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
<p:dataTable
var="element"
value="#{bean.elements}"
selection="#{bean.selectedElement}"
selectionMode="single"
rowKey="#{element.id}"
tableStyle="width: auto !important;">
<p:ajax
event="rowSelect"
oncomplete="PF('elementDialog').show();" />
...
</p:dataTable>
The Data class:
public class Data implements Serializable {
private int id; // + getter/setter
private String key, val; // + getter/setter
public Data(int id, String key, String value) {
super();
this.setId(id);
this.key = key;
this.value = value;
}
}
The bean:
public class Bean implements Serializable {
private List<Data> elements; // + getter
private Data selectedElement; // + getter/setter
#PostConstruct
public void init() {
elements = new ArrayList<>();
elements.add(new Data(0, "Elem 1 Key", "Elem 1 Value"));
elements.add(new Data(1, "Elem 2 Key", "Elem 2 Value"));
}
}
Hopefully this example leads you to archive your goal ... ;)

Primefaces datatable and ViewScoped

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>.

Primefaces datatable filter doesn't work

I must do something fundamentally wrong, I stripped down the code to the bare minimum with a data table and enabling one column filter and a globe filter.
The funny thing is that the example code from Primefaces works. The only difference to my code should be that it gathers data from a DB rather than generating it in the bean.
I have no more clues why my example doesn't do anything when I type something in the filter would be appreciate any ideas here.
My xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<ui:composition template="layout.xhtml">
<ui:define name="title">All Projects</ui:define>
<ui:define name="content">
<p:dataTable var="project" value="#{projectController.allProjects}" widgetVar="projectTable" filteredValue="#{projectController.filteredProjects}">
<f:facet name="header">
<p:outputPanel>
<h:outputText value="Search all fields:" />
<p:inputText id="globalFilter" onkeyup="PF('projectTable').filter()" style="width:150px" />
</p:outputPanel>
</f:facet>
<p:column headerText="Name" filterBy="#{project.name}">
<h:outputText value="#{project.name}" />
</p:column>
<p:column headerText="Priority">
<h:outputText value="#{project.priority}" />
</p:column>
<p:column headerText="Exit">
<h:outputText value="#{project.exitCriteria}" />
</p:column>
</p:dataTable>
</ui:define>
</ui:composition>
My Bean:
package com.apa.projectd.common;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.bean.ManagedBean;
import javax.inject.Inject;
import com.habony.common.Loggable;
import com.habony.projectd.ejbs.ProjectEJB;
import com.habony.projectd.enteties.Project;
#ManagedBean(name="projectController")
#SessionScoped
#Loggable
public class ProjectController implements Serializable{
private static final long serialVersionUID = 8345760187637787728L;
#Inject
private ProjectEJB projectEJB;
private List<Project> filteredProjects;
private List<Project> allProjects;
#PostConstruct
public void loadAllProjects(){
allProjects = projectEJB.getAllProjects();
}
//
// Getters and Setters
//
public List<Project> getFilteredProjects() {
return filteredProjects;
}
public void setFilteredProjects(List<Project> filteredProjects) {
this.filteredProjects = filteredProjects;
}
public void setAllProjects(List<Project> allProjects) {
this.allProjects = allProjects;
}
public List<Project> getAllProjects(){
return allProjects;
}
}
The filters features of p:dataTable need to be wrapped in <h:form> tags for work fine. The code xhtml modified would:
<!DOCTYPE html>
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<ui:composition template="layout.xhtml">
<ui:define name="title">All Projects</ui:define>
<ui:define name="content">
<h:form>
<p:dataTable var="project" value="#{projectController.allProjects}" widgetVar="projectTable" filteredValue="#{projectController.filteredProjects}">
<f:facet name="header">
<p:outputPanel>
<h:outputText value="Search all fields:" />
<p:inputText id="globalFilter" onkeyup="PF('projectTable').filter()" style="width:150px" />
</p:outputPanel>
</f:facet>
<p:column headerText="Name" filterBy="#{project.name}">
<h:outputText value="#{project.name}" />
</p:column>
<p:column headerText="Priority">
<h:outputText value="#{project.priority}" />
</p:column>
<p:column headerText="Exit">
<h:outputText value="#{project.exitCriteria}" />
</p:column>
</p:dataTable>
</h:form>
</ui:define>
</ui:composition>
Please see lazy property this may be that your data not filter.
lazy="true" change lazy=false
finally I figured out that when you use Lazy the filtered data is not stored in other variable as in non lazy implementation, everytime you call a filter the load method is executed, so I had to put the filters also in my Load, also the sorting this is the way when using Lazy.
My mistake !
You should initialize filtredProjects with the same data that contains the ArrayList allProjects like this:
#PostConstruct
public void loadAllProjects(){
allProjects = projectEJB.getAllProjects();
filtredProjects = projectEJB.getAllProjects();
}
Do not use lazy loading when filtering and/or sorting

Input given in JSF page does not set that value to managed bean variable [duplicate]

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")

Primefaces Delete & Confirm Dialog inside table column - Update or Freeze Issue

I have a smiliar problem like here: Primefaces: commandButton in confirmDialog cannot update datatable in the same form
I have a table with games. In the last column there are 2 buttons: delete and details.
The delete button should delete the game
The button does delete the game but the update doesn't work.
update=":form1:overviewTableGame" --> no reaction (no refresh)
update="#form" --> update performes (table refreshes), but the entire scren is locked. i think due to the fact, that the form which contains the dialog is updated...
The table code:
<h:form id="form1">
<p:messages id="messages" showDetail="true" autoUpdate="true"
closable="true" />
<p:dataTable id="overviewTableGame" var="game" value="#{gameMB.list}">
<p:column headerText="#{msg.ID}" sortBy="#{game.id}">
<h:outputText value="#{game.id}" />
</p:column>
<p:column headerText="#{msg.NAME}" sortBy="#{game.name}">
<h:outputText value="#{game.name}" />
</p:column>
<p:column headerText="#{msg.DESCRIPTION}"
sortBy="#{game.description}">
<h:outputText value="#{game.description}" />
</p:column>
<p:column headerText="#{msg.ADMIN}" sortBy="#{game.admin.firstname}">
<h:outputText value="#{game.admin.firstname}" />
</p:column>
<p:column headerText="#{msg.ACTION}">
<p:commandButton id="commandButtonDELETE" value="löschen"
onclick="confirmation.show()" type="button"
update=":form1:display">
<f:setPropertyActionListener value="#{game}"
target="#{gameMB.selectedGame}" />
</p:commandButton>
<p:commandButton id="commandButtonDETAIL" value="detail"
action="#{gameMB.details()}">
<f:param name="id" value="#{game.id}" />
</p:commandButton>
</p:column>
</p:dataTable>
<p:confirmDialog id="confirmDialog"
message="Are you sure about destroying the world?"
header="Initiating destroy process" severity="alert"
widgetVar="confirmation">
<h:panelGrid id="display" columns="2" cellpadding="4"
style="margin:0 auto;">
<h:outputText value="Name:" />
<h:outputText value="#{gameMB.selectedGame.name}"
style="font-weight:bold" />
<p:commandButton id="confirm" value="Yes Sure"
oncomplete="confirmation.hide()"
actionListener="#{gameMB.delete(gameMB.selectedGame)}"
update=":form1:overviewTableGame">
</p:commandButton>
</h:panelGrid>
<p:commandButton id="decline" value="Not Yet"
onclick="confirmation.hide()" type="button" />
</p:confirmDialog>
</h:form>
The Delete Method:
public void delete(Game game) {
//FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,"DELETE", "Game Deleted!"));
System.out.println("==================");
System.out.println(game);
getGameService().removeGame(game);
//this.gameList = gameService.listAllGames();
}
The selectedGame
private Game selectedGame;
public Game getSelectedGame() {
return selectedGame;
}
public void setSelectedGame(Game selectedGame) {
this.selectedGame = selectedGame;
}
Any ideas?
Thanks
Separate your dialog from p:dataTable. Following code is working:
The xhtml:
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui" template="/WEB-INF/templates/globalTemplate.xhtml">
<ui:define name="title">15344819</ui:define>
<ui:define name="content">
<p:growl id="growl" showDetail="true" />
<h:form id="form">
<p:dataTable id="students" value="#{so15344819.students}" var="student">
<p:column>
<p:commandButton id="selectButton" update=":form:display" oncomplete="studentDialog.show()" icon="ui-icon-search" title="View">
<f:setPropertyActionListener value="#{student}" target="#{so15344819.selectedStudent}" />
</p:commandButton>
</p:column>
</p:dataTable>
<p:dialog header="Student Detail" widgetVar="studentDialog" resizable="false" id="studentDlg"
showEffect="fade" hideEffect="explode" modal="true">
<h:panelGrid id="display" columns="2" cellpadding="4" style="margin:0 auto;">
<h:outputText value="Name:" />
<h:outputText value="#{so15344819.selectedStudent.name}" style="font-weight:bold"/>
<p:commandButton id="deleteButton" actionListener="#{so15344819.delete(so15344819.selectedStudent)}" oncomplete="studentDialog.hide()"
update=":form:students" value="Delete"/>
<p:commandButton id="cancelButton" onclick="studentDialog.hide()" value="Cancel"/>
</h:panelGrid>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>
The managed bean:
package app.so.dev.web.controller;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import app.so.dev.web.model.Student;
#ManagedBean(name = "so15344819")
#ViewScoped
public class SO15344819 implements Serializable {
private static final long serialVersionUID = 6686378446131077581L;
private List<Student> students;
private Student selectedStudent;
#PostConstruct
public void init() {
students = new ArrayList<Student>();
students.add(new Student("Student 1"));
students.add(new Student("Student 2"));
}
public void delete(Student student) {
System.out.println("==================");
System.out.println(student);
students.remove(student);
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public Student getSelectedStudent() {
return selectedStudent;
}
public void setSelectedStudent(Student selectedStudent) {
this.selectedStudent = selectedStudent;
}
}
Feel free to revert.