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

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

Related

p:datatable summary row calculation

I have a p:dataTable pretty similar to the showcase.
Unfortunatly, the showcase uses randomly generated values for the p:summaryRow.
Refering to the showcase, imagine the car had a price attribute.
How would I sum up the price for the cars grouped by the specified column for displaying it in the summary row?
I have same problem with you and found correct usage from primefaces blog
SummaryRow from primefaces forum
this is some example show correct calculation for sum price, count...
Listener gets the group property which is the sortBy value which you can use to calculate totals or any other operation.
<p:summaryRow listener="#{backingBean.calculateTotal}">
<p:column colspan="3" style="text-align:right">
Total:
</p:column>
<p:column>
#{backingBean.total}
</p:column>
</p:summaryRow>
/* listener method in your bean */
public void calculateTotal(Object o) {
this.total = 0.0d;
String name = "";
if(o != null) {
if(o instanceof String) {
name = (String) o;
for(MyRowObject p : (List<MyRowObject>) dataTableModel.getWrappedData()) { // The loop should find the sortBy value rows in all dataTable data.
switch(sortColumnCase) { // sortColumnCase was set in the onSort event
case 0:
if(p.getcolumn0data().getName().equals(name)) {
this.total += p.getcolumn0data().getValue();
}
break;
case 1:
if(p.getcolumn1data().getName().equals(name)) {
this.total += p.getcolumn1data().getValue();
}
break;
}
}
}
}
}
this is my solution:
<p:dataTable var="elem" value="#{unitSubStatusChart.resultList}" tableStyleClass="app-table-auto">
<et:defaultPaginator />
<p:column headerText="#{bundle['class']}" sortBy="#{elem.dtype}">
<e:outputIconText icon="#{icons[elem.dtype]}" value="#{bundle[elem.dtype]}" />
</p:column>
<p:column headerText="#{bundle['status']}" sortBy="#{elem.status}">
<h:outputText value="#{bundle[elem.status]}" />
</p:column>
<p:column headerText="#{bundle['subStatus']}" sortBy="#{elem.subStatus}">
<h:outputText value="#{bundle[elem.subStatus]}" />
</p:column>
<p:column headerText="#{bundle['count']}">
<h:outputText value="#{elem.count}" />
</p:column>
<p:summaryRow listener="#{unitSubStatusChart.onSummaryRow}">
<p:column colspan="3" style="text-align:right">
<h:outputText value="#{bundle.total}:" />
</p:column>
<p:column>
<!-- !!! NOTE THIS VALUE EXPRESSION !!! -->
<h:outputText value="#{component.parent.attributes.total}" />
</p:column>
</p:summaryRow>
</p:dataTable>
and this is the listener:
public void onSummaryRow(Object filter)
{
FacesContext facesContext = FacesContext.getCurrentInstance();
ELContext elContext = facesContext.getELContext();
ELResolver elResolver = elContext.getELResolver();
DataTable table = (DataTable) UIComponent.getCurrentComponent(facesContext);
UIColumn sortColumn = table.getSortColumn();
ValueExpression expression = sortColumn.getValueExpression("sortBy");
ValueReference reference = ValueExpressionAnalyzer.getReference(expression);
String property = (String) reference.getProperty();
int total = 0;
List<?> rowList = (List<?>) table.getValue();
for(Object row : rowList)
{
Object value = elResolver.getValue(elContext, row, property);
if(filter.equals(value))
{
// THIS IS THE ONLY POINT TO CUSTOMIZE
total += ((UnitResult) row).getCount();
}
}
List<UIComponent> children = table.getSummaryRow().getChildren();
UIComponent column = children.get(children.size() - 1);
column.getAttributes().put("total", total);
}
This listener has no external references: it does not depend on previous onSort events/listeners and it doesn't need any field in the bean.
I will suggest a possible way to do this, may not be the most perfect, but i believe it will help.
Ther's the steps:
1 - Declare a class atribute to acumulate the total group value:
...
#Named(value = "myBean")
#YourScope
public class InscricaoBean implements Serializable {
...
//in this example i will use a int type
private int acumulatorAux = 0;
...
2 - Create a function to return the total value per group:
...
public int getAcumulatedValue() {
int aux = acumulatorAux ;
acumulatorAux = 0;
return aux;
}
...
3 - Create an method to acumulate values per group:
...
public void acumulateValue(int value)
{
acumulatorAux += value;
}
...
4 - On JSF page, you need to call acumulateValue method for every row, something like:
...
<p:dataTable value="#{myBean.getList()}" var="testVar">
<p:column headerText="Header" sortBy="#{testVar.name}">
#{inscricaoBean.acumulateValue(testVar.value)}
<h:outputText value="#{testVar.name}" />
</p:column>
...
5 - And next, you can have a summaryRow like:
...
<p:summaryRow>
<p:column colspan="1" style="text-align:right">
<h:outputText value="Total:" />
</p:column>
<p:column>
<h:outputText value="#{inscricaoBean.getAcumulatedValue()}" />
</p:column>
</p:summaryRow>
...
Well, this is a gross way to acomplish this task. I think you can improve, but it was the first think when i see your question.
Hope it helps.
by using Lambda expression it works in java 1.7 with EL 3.0
n your JSF it would be like this :
<p:summaryRow>
<p:column colspan="3" style="text-align:right">
<h:outputText value="Total:" />
</p:column>
<p:column>
<h:outputText value="#{car.stream().map(item->item.price).sum()}">
<f:convertNumber type="currency" currencySymbol="$" />
</h:outputText>
</p:column>
</p:summaryRow>
One approach is to pass the datatable's sortBy="#{car.brand}" value within the p:summaryRow into a backing method that uses a stream to compute price subtotal.
<h:form>
<p:dataTable var="car" value="#{dtSummaryRowView.cars}" sortBy="#{car.brand}">
<p:column headerText="Id" sortBy="#{car.id}">
<h:outputText value="#{car.id}" />
</p:column>
<p:column headerText="Year" sortBy="#{car.year}">
<h:outputText value="#{car.year}" />
</p:column>
<p:column headerText="Brand" sortBy="#{car.brand}">
<h:outputText value="#{car.brand}" />
</p:column>
<p:column headerText="Color" sortBy="#{car.color}">
<h:outputText value="#{car.color}" />
</p:column>
<p:summaryRow>
<p:column colspan="3" style="text-align:right">
<h:outputText value="Total:" />
</p:column>
<p:column>
<h:outputText value="#{dtSummaryRowView.brandSubtotal(car.brand)}">
<f:convertNumber type="currency" currencySymbol="$" />
</h:outputText>
</p:column>
</p:summaryRow>
</p:dataTable>
</h:form>
.
public double brandSubtotal(String brand) {
return cars.stream().filter(c -> c.getBrand().equals(brand)).mapToDouble(c -> c.getPrice()).sum();
}
Another approach is to use the listener in p:summaryRow to set a backing bean attribute and then use getter to display the attribute.
<p:summaryRow listener="#{dtSummaryRowView.computeSubtotal(car.brand)}">
<p:column colspan="3" style="text-align:right">
<h:outputText value="Total:" />
</p:column>
<p:column>
<h:outputText value="#{dtSummaryRowView.subTotal}">
<f:convertNumber type="currency" currencySymbol="$" />
</h:outputText>
</p:column>
</p:summaryRow>
.
public void computeSubtotal(String brand) {
subTotal = cars.stream().filter(c -> c.getBrand().equals(brand)).mapToDouble(c -> c.getPrice()).sum();
}
public double getSubTotal () {
return subTotal ;
}

Primefaces dialog fields not filled after click in CommandLink

I am using Primefaces 3.5 with Weblogic 11. I have a page where a dialog to edit a 'profile' entity ('perfil' in Portuguese) which is called from two places. First from a commandButton to insert a new profile. The second from a dataTable to edit a specific profile. Below, I show the code:
Snippet of XHTML page
<p:fieldset legend="Pesquisa de Perfil">
<p:panelGrid columns="2">
<f:facet name="footer">
<p:commandButton id="btnPesquisar"
actionListener="#{perfilAcessoMB.pesquisar}" value="Pesquisar"
immediate="true" update="pnlPerfis" styleClass="ui-icon-search" />
<p:spacer width="20"></p:spacer>
<!-- OPEN DIALOG TO CREATE A NEW PROFILE -->
<p:commandButton id="btnIncluir" value="Incluir"
update="dlgPerfil" immediate="true"
actionListener="#{perfilAcessoMB.abrirDialogoEdicao(null)}"
oncomplete="dlgPerfil.show();">
</p:commandButton>
</f:facet>
</p:panelGrid>
</p:fieldset>
<br />
<p:outputPanel id="pnlPerfis" layout="block">
<p:fieldset id="resultadoPesquisa" legend="Resultado da Pesquisa"
rendered="#{not empty perfilAcessoMB.perfis}">
<p:dataTable id="tblPerfis" value="#{perfilAcessoMB.perfis}"
var="perfil" emptyMessage="Nenhum perfil encontrado.">
<p:column headerText="Nome do Perfil">
<h:outputText value="#{perfil.nome}"></h:outputText>
</p:column>
<p:column headerText="Descrição do Perfil">
<h:outputText value="#{perfil.descricao}"></h:outputText>
</p:column>
<p:column headerText="Situação do Perfil"
style="text-align: center; width: 100px;">
<h:outputText value="Ativo" rendered="#{perfil.situacao}" />
<h:outputText value="Inativo" rendered="#{not perfil.situacao}" />
</p:column>
<p:column headerText="Editar"
style="text-align: center; width: 50px;">
<!-- OPEN DIALOG TO EDIT A NEW PROFILE -->
<p:commandLink id="lnkEditar" immediate="true"
title="Editar Perfil" update=":formPrincipal:dlgPerfil :formPrincipal:pnlPerfilEdicao"
actionListener="#{perfilAcessoMB.abrirDialogoEdicao(perfil)}"
oncomplete="dlgPerfil.show();">
<h:outputText value="Editar" />
</p:commandLink>
</p:column>
<p:column headerText="Excluir"
style="text-align: center; width: 50px;">
</p:column>
</p:dataTable>
</p:fieldset>
</p:outputPanel>
<p:dialog id="dlgPerfil" widgetVar="dlgPerfil" resizable="false"
closable="true" modal="true" closeOnEscape="true"
header="#{(empty perfilAcessoMB.perfil)? 'Incluir': 'Editar'} Perfil">
<h:outputText value="#{perfilAcessoMB.perfil}"></h:outputText>
<h:panelGroup id="pnlPerfilEdicao" layout="block">
<p:fieldset legend="Dados do Perfil">
<p:panelGrid columns="2">
<h:outputLabel id="lblNomePerfilEdicao" value="Nome do Perfil"
for="txtNomePerfilEdicao" />
<p:inputText id="txtNomePerfilEdicao" required="true"
requiredMessage="É obrigatório preencher o campo Nome do Perfil."
value="#{perfilAcessoMB.perfil.nome}" maxlength="20" size="20"></p:inputText>
<h:outputLabel id="lblDescricaoPerfilEdicao"
value="Descrição do Perfil" for="txtDescricaoPerfilEdicao" />
<p:inputText id="txtDescricaoPerfilEdicao" required="true"
requiredMessage="É obrigatório preencher o campo Descrição do Perfil."
value="#{perfilAcessoMB.perfil.descricao}" maxlength="20"
size="20"></p:inputText>
<h:outputLabel id="lblSituacaoPerfilEdicao" value="Situação"
for="selSituacaoPerfilEdicao" />
<p:selectOneMenu id="selSituacaoPerfilEdicao"
value="#{perfilAcessoMB.perfil.situacao}">
<f:selectItems value="#{perfilAcessoMB.situacoesEdicao}" />
</p:selectOneMenu>
</p:panelGrid>
</p:fieldset>
<br />
<p:fieldset legend="Permissões">
<p:pickList id="pickFuncoes" value="#{perfilAcessoMB.funcoes}"
var="funcao" itemValue="#{funcao}"
itemLabel="#{funcao.descricao}" required="true"
requiredMessage="É obrigatório associar ao menos uma funcionalidade ao perfil."
converter="funcaoConverter" />
<p:column>#{funcao.descricao}</p:column>
</p:fieldset>
<p:panelGrid columns="2">
<p:commandButton id="btnSalvarPerfil" value="Salvar"
actionListener="#{perfilAcessoMB.salvar}"
oncomplete="if(args && !args.validationFailed) dlgPerfil.hide();" />
<p:commandButton id="btnCancelarPerfil" value="Cancelar"
immediate="true" onclick="dlgPerfil.hide();" />
</p:panelGrid>
</h:panelGroup>
</p:dialog>
MangedBean (perfilAcessoMB)
#ManagedBean
#ViewScoped
public class PerfilAcessoMB extends BaseMB {
private PerfilAcessoORM perfil;
private List<PerfilAcessoORM> perfis;
private String nomePerfil;
private Boolean situacao;
private DualListModel<FuncaoORM> funcoes;
private SelectItem[] situacoesPesquisa = new SelectItem[] {
new SelectItem(null, "Todos"), SELECT_ITEM_ATIVO,
SELECT_ITEM_INATIVO };
private SelectItem[] situacoesEdicao = new SelectItem[] {
SELECT_ITEM_ATIVO, SELECT_ITEM_INATIVO };
private FuncaoORM funcaoA = new FuncaoORM(1L, "FUNÇÃO A"), //
funcaoB = new FuncaoORM(2L, "B Function"), //
funcaoC = new FuncaoORM(10L, "Se Funssaum");
public void abrirDialogoEdicao(PerfilAcessoORM p) {
this.perfil = (p == null)? new PerfilAcessoORM(): p;
System.out.println("PerfilAcessoMB.onAbrirDialogoEdicao(): "
+ this.perfil);
List<FuncaoORM> funcoesDisponiveis = new ArrayList<FuncaoORM>(
Arrays.asList(funcaoA, funcaoB, funcaoC));
// Remove from funcoesDisponiveis those whose are present in perfil.
if (this.perfil.getFuncoes() == null) {
this.funcoes = new DualListModel<FuncaoORM>(funcoesDisponiveis,
Lists.<FuncaoORM> newArrayList());
} else {
funcoesDisponiveis.removeAll(this.perfil.getFuncoes());
this.funcoes = new DualListModel<FuncaoORM>(funcoesDisponiveis,
this.perfil.getFuncoes());
}
}
// Getters & Setters
}
PerfilAcessoORM (Profile) Entity
public class PerfilAcessoORM {
private Long id;
private String nome;
private String descricao;
private Boolean situacao = null;
private List<FuncaoORM> funcoes;
// Getters & Setters
}
FuncaoORM Entity:
public class FuncaoORM {
private Long id;
public String descricao;
// Getters & Setters
}
What is my problem? Apparently, when I want insert a new Profile, all seems OK. However, when I click to edit an existent profile to open the dialog, although the outputText and pickList are correctly filled, the inputText's and selectOneMenu are not.
Looking for solutions, I found here a suggestion to use appendToBody="true" in dialog. When I tried, the inputText's and selectOneMenu are correctly filled. However, the validation is not working as waited. When I click to save it is showed a message indicating that pickList is not filled, even if it is really filled. Actually, even if inputText's are not filled, there is no message about these inputTexts although they are required.
Another alternative would be use <f:setPropertyActionListener> inside commandLink:
<!-- OPEN DIALOG TO CREATE A NEW PROFILE -->
<p:commandButton id="btnIncluir" value="Incluir"
update="dlgPerfil" immediate="true"
actionListener="#{perfilAcessoMB.abrirDialogoEdicao}"
oncomplete="dlgPerfil.show();">
<f:setPropertyActionListener target="#{perfilAcessoMB.perfil}" value="#{null}"/>
</p:commandButton>
<!-- OPEN DIALOG TO EDIT A NEW PROFILE -->
<p:commandLink id="lnkEditar" immediate="true"
title="Editar Perfil" update=":formPrincipal:dlgPerfil :formPrincipal:pnlPerfilEdicao"
actionListener="#{perfilAcessoMB.abrirDialogoEdicao}"
oncomplete="dlgPerfil.show();">
<f:setPropertyActionListener target="#{perfilAcessoMB.perfil}" value="#{perfil}"/>
<h:outputText value="Editar" />
</p:commandLink>
The actionListener method would changed to:
public void abrirDialogoEdicao() {
if(this.perfil == null) {
this.perfil = new PerfilAcessoORM();
}
System.out.println("PerfilAcessoMB.onAbrirDialogoEdicao(): "
+ this.perfil);
// The rest remains the same ...
}
Now, when I click to create a new perfil, although in actionListener method the perfil attribute is filled, I got a NullPointerException when the dialog is renderized. It is like first is called perfilAcessoMB.setPerfil(), after the dialog is opened and finally actionListener method. On the other hand, if I click to edit an existent profile, I return to initial situation.
Therefore, I am lost, without idea how to solve this issue.
Thanks,
Rafael Afonso
The solution was incredible simple: just added process="#this" to both commandButtons.
<!-- OPEN DIALOG TO EDIT A NEW PROFILE -->
<p:commandLink id="lnkEditar" immediate="true"
title="#{msg['titulo.edicao']}" process="#this"
update=":formPrincipal:dlgPerfil"
actionListener="#{perfilAcessoMB.abrirDialogoEdicao(perfil)}"
oncomplete="dlgPerfil.show();">
<h:outputText value="#{msg['titulo.edicao']}" />
</p:commandLink>

Selected row is null using different forms

I am getting a null selected row when I press the showDialog command button
I can't see what is my problem
This is my first form:
<h:form id="firstForm">
<p:commandButton action="#{testBB.showDialog}" id="showDialog"
update=":secondForm" value="#{msg['show.dialog']}" />
</h:form>
This is my second form:
<h:form id="secondForm">
<p:dataTable id="testDatatable"
rendered="#{not empty testBB.list}"
rowKey="#{order.orderNumber}"
selection="#{testBB.selectedRow}"
selectionMode="single"
sortBy="customerName" value="#{testBB.list}" var="order">
<p:column headerText="#{msg['order.number']}">
<h:outputText value="#{order.orderNumber}" />
</p:column>
<p:column headerText="#{msg['total.value']}">
<h:outputText value="#{order.totalValue}" />
</p:column>
</p:dataTable>
</h:form>
My backing bean:
#ManagedBean
#ViewScoped
public class TestBB implements Serializable {
private List<Order> list;
private Order selectedRow;
public void showOrder() {
try {
System.out.println(selectedRow);
} catch (Exception exception) {
}
}
}
And my DTO:
public class Order implements Serializable {
private int orderNumber;
private double totalValue;
public void showOrder() {
try {
System.out.println(selectedRow);
} catch (Exception exception) {
}
}
/** Getters and setters */
}
What is wrong in my code?
Put
<p:ajax event="rowSelect" />
<p:ajax event="rowUnselect" />
inside your datatable for selection/unselection to happen as soon as click happens.
If you need selection only on button click use 'process' like this
<p:commandButton process=":secondForm:testDatatable" update=":secondForm"/>
You need to update the model on rowSelection. This can be done using a <p:ajax event="rowSelect" />. Here is how I think your Datatable should look like:
<p:dataTable id="testDatatable"
rendered="#{not empty testBB.list}"
rowKey="#{order.orderNumber}"
selection="#{testBB.selectedRow}"
selectionMode="single"
sortBy="customerName" value="#{testBB.list}" var="order">
<p:ajax event="rowSelect" />
<p:column headerText="#{msg['order.number']}">
<h:outputText value="#{order.orderNumber}" />
</p:column>
<p:column headerText="#{msg['total.value']}">
<h:outputText value="#{order.totalValue}" />
</p:column>
</p:dataTable>
A good example can be found here (Primefaces Demo).
As Kerem Baydogan suggested you have to include process attribute with your data table id in your command button.
If you are not including process attribute then no components will be processed in the component tree and no modal values will be updated hence you are getting selection as null.
I feel there is no need of updating data table if you are not changing its state.

how to get the database values by using hibernate and how to display that values in a primefaces dataTable?

Here i have some doubts.If you know the answer please post here.
How to get the list of values into database table by using hibernate?
How to display that values into primefaces dataTable?
Here i am posting what i am trying .see below
<p:dataTable id="users" value="#{user.listUsers}" var="user"
sortBy="user.id" rows="10" style="width: 30%">
<p:column>
<f:facet name="header">
<h:outputText value="ID" />
</f:facet>
<h:outputText value="#{user.id}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{user.name}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Surname" />
</f:facet>
<h:outputText value="#{user.surName}" />
</p:column>
</p:dataTable>
Here i am finding the answer how to display a table values into primefaces dataTable.
Here i am placing what i am trying code.
<p:dataTable value="#{actions.messages}" var="act">
<p:column style="width:10%;text-align:left" filterBy="#{act.id}" >
<f:facet name="header">
<h:outputText value="ID" id="id" />
</f:facet>
<h:outputText value="#{act.id}" />
</p:column>
<p:column style="width:20%;text-align:left"
sortBy="#{act.action}">
<f:facet name="header">
<h:outputText value="Customer" id="customer" />
</f:facet>
<h:outputText value="#{act.action}" />
</p:column>
<p:column style="width:40%;text-align:left"
sortBy="#{act.scheduled}">
<f:facet name="header">
<h:outputText value="Date" />
</f:facet>
<h:outputText value="#{act.scheduled}" />
</p:column>
<p:column style="width:30%;text-align:left"
sortBy="#{act.status}">
<f:facet name="header">
<h:outputText value="Action" />
</f:facet>
<h:outputText value="#{act.status}" />
</p:column>
</p:dataTable>
Here is the hibernate dao class name called ActionsDao
public class ActionsDao {
public Session session;
public ArrayList<Actions> getActions() {
session = Util.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
try {
#SuppressWarnings("unchecked")
ArrayList<Actions> actionsList = (ArrayList<Actions>) session
.createQuery("from Actions").list();
tx.commit();
boolean found = false;
for (Actions actions : actionsList) {
Actions action = new Actions();
action.setId(actions.getId());
action.setAction(actions.getAction());
action.setActual(actions.getActual());
action.setAssignedBy(actions.getAssignedBy());
action.setAssignedTo(actions.getAssignedTo());
action.setScheduled(actions.getScheduled());
action.setOutcome(actions.getOutcome());
action.setStatus(actions.getStatus());
actionsList.contains(action);
found = true;
}
if (found) {
return actionsList;
} else {
return null;
}
} catch (Exception e) {
System.out.println("Error In getActions() -->" + e.getMessage());
return (null);
} finally {
session.close();
}
}
}
Here is the bean class i am developing name called Actions.
#ManagedBean(name = "actions", eager = true)
#SessionScoped
public class Actions implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String action;
private String assignedTo;
private String assignedBy;
private Date scheduled;
private Date actual;
private String outcome;
private String status;
//write here setter & getter methods of the above properties
public ArrayList<Actions> getMessages() {
ActionsDao dao = new ActionsDao();
return dao.getActions();
}
}
you can use the annotations or hbm file that yours choice to map the bean class.
Here i am using only mapping file why because, first i am trying to create annotations but it raised some problems that jar files are some problem.your using the correct jar files that not a problem you can continue the annotations otherwise hbm file is best.

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.