Hi
How do I make a single row selection in p:dataTable rerender a detail p:dataTable using onSelectComplete in a master-detail data relation using ajax postback?
The funtion that I am seeking is that when I select a row in the master table related detail record information must be displayed in the detail table.
In the show case samples has implemented displaying row details in a dialog using the dialog.show() and dialog.hide() methods in the onSelectComplete but I fail to find any methods on the DataTable widget allowing me to refresh my detailTbl widgetVar?
Is there any way to implement this?
I realize that I have to do somthing like this:
<p:dataTable id="masterTable" widgetVar="masterTbl" selection="#{myBean.masterModel}" .... onSelectComplete="detailTbl.<what method to call here on the widget?>" update="detailTable">
...
...
</p:dataTable>
<p:dataTable id="detailTable" widgetVar="detailTbl" selection="#{myBean.detailModel}">
...
...
</p:dataTable>
Datatable onSelectComplete rendering detail datatable
HI,
Here is a slightly modified version of the showcase example. The p:dialog is no longer there and the p:dataTables onselectComplete is no longer used. If you structure your page in a similar way, I think you'll get what you need.
Here is a slightly modified version of the showcase example. The p:dialog is no longer there and the p:dataTables onselectComplete is no longer used. If you structure your page in a similar way, I think you'll get what you need.
Code: Select all
<h:form prependId="false">
<p:dataTable var="car" value="#{tableBean.cars}" paginator="true" rows="10"
selection="#{tableBean.selectedCar}" selectionMode="single" update="display">
<p:column>
<f:facet name="header">
<h:outputText value="Model" />
</f:facet>
<h:outputText value="#{car.model}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Year" />
</f:facet>
<h:outputText value="#{car.year}" />
</p:column>
</p:dataTable>
<h:panelGrid id="display" columns="2">
<h:outputText value="Model:" />
<h:outputText value="#{tableBean.selectedCar.model}" style="font-weight:bold"/>
<h:outputText value="Year:" />
<h:outputText value="#{tableBean.selectedCar.year}" style="font-weight:bold"/>
<h:outputText value="Manufacturer:" />
<h:outputText value="#{tableBean.selectedCar.manufacturer}" style="font-weight:bold"/>
<h:outputText value="Color:" />
<h:outputText value="#{tableBean.selectedCar.color}" style="font-weight:bold"/>
</h:panelGrid>
</h:form>
Hi bmacmanus
Thank you for your answer.
Mayby I need to add my sample of what I want to do.
The when clicking on a row on in the top table i want to lazy load data into the 2nd table.
Her I need a metod in:
onselectComplete="detailsTable.update();">
Thank you for your answer.
Mayby I need to add my sample of what I want to do.
The when clicking on a row on in the top table i want to lazy load data into the 2nd table.
Her I need a metod in:
onselectComplete="detailsTable.update();">
Code: Select all
<h:form styleClass="jsfcrud_list_form">
<p:dataTable widgetVar="masterTable" value="#{item.lazyModel}" var="item1" id="dataTable" paginator="true" rows="10" lazy="true" dynamic="true" selectionMode="single" selection="#{item.item}"
rowsPerPageTemplate="5,10,20,50,100" paginatorTemplate="{PreviousPageLink} {CurrentPageReport} {NextPageLink} {RowsPerPageDropdown}" page="#{item.page}" update="detailsTbl" onselectComplete="detailsTable.update();">
<p:column >
<f:facet name="header">
<h:outputText value="Id"/>
</f:facet>
<h:outputText value="#{item1.id}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:outputText value="#{item1.name}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText escape="false" value=" "/>
</f:facet>
<h:commandLink value="Show" action="#{item.detailSetup}">
</h:commandLink>
<h:outputText value=" "/>
<h:commandLink value="Edit" action="#{item.editSetup}">
<f:setPropertyActionListener value="#{item1}" target="#{item.item}" />
</h:commandLink>
<h:outputText value=" "/>
<h:commandLink value="Destroy" action="#{item.destroy}">
<f:setPropertyActionListener value="#{item1}" target="#{item.item}" />
</h:commandLink>
</p:column>
</p:dataTable>
<p:messages/>
<hr>
<p:panel rendered="true">
<p:dataTable id="detailTbl" widgetVar="detailsTable" value="#{item.lazyDetailModel}" var="detail" dynamic="true" lazy="true" rows="10">
<p:column>
<f:facet name="header">
<h:outputText value="Value1"/>
</f:facet>
<h:outputText value="#{detail.value}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Value2"/>
</f:facet>
<h:outputText value="#{detail.value2}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Value3"/>
</f:facet>
<h:outputText value="#{detail.value3}"/>
</p:column>
</p:dataTable>
</p:panel>
<br />
Hi,
I've looked at your code, but I still don't underdstand why it's necessary to manually update the details-table with Javascript after a row in the master-table is selected. The master-table uses the instant ajax row selection feature and should therefore be able to update the details-table automatically by specifying the id of the details-table component in the update attribute of the master-table component.
Your details-table is wrapped in a <p:panel rendered="true"> component. rendered is always set to true here, but if it ever happens to be false, the details-table will not be rendered. If the details-table is not rendered, it will not be physically present on the html page. If it's not physically present on the html page, it will be impossible to update it! Perhaps this is the source of the problems.
Here is an example that works with PrimeFaces 2.0.2. The master-table displays books, and the details-table displays authors.
Page:
Bean:
Book:
Author:
I've looked at your code, but I still don't underdstand why it's necessary to manually update the details-table with Javascript after a row in the master-table is selected. The master-table uses the instant ajax row selection feature and should therefore be able to update the details-table automatically by specifying the id of the details-table component in the update attribute of the master-table component.
Your details-table is wrapped in a <p:panel rendered="true"> component. rendered is always set to true here, but if it ever happens to be false, the details-table will not be rendered. If the details-table is not rendered, it will not be physically present on the html page. If it's not physically present on the html page, it will be impossible to update it! Perhaps this is the source of the problems.
Here is an example that works with PrimeFaces 2.0.2. The master-table displays books, and the details-table displays authors.
Page:
Code: Select all
<?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.prime.com.tr/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
</h:head>
<h:body>
<h:form prependId="false">
<p:dataTable id="bookTable"
value="#{bookAuthors.lazyBooks}"
var="book"
dynamic="true"
lazy="true"
selectionMode="single"
selection="#{bookAuthors.currentBook}"
update="authorsContent"
paginator="true"
rows="5"
rowsPerPageTemplate="5,10,20,50,100"
paginatorTemplate="{PreviousPageLink} {CurrentPageReport} {NextPageLink} {RowsPerPageDropdown}">
<p:column>
<f:facet name="header">
<h:outputText value="Title"/>
</f:facet>
<h:outputText value="#{book.title}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Text"/>
</f:facet>
<h:outputText value="#{book.text}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Info"/>
</f:facet>
<p:commandLink value="Info" oncomplete="dlg.show();" update="bookDialogContent">
<f:setPropertyActionListener value="#{book}" target="#{bookAuthors.currentBook}" />
</p:commandLink>
</p:column>
</p:dataTable>
<p:outputPanel id="authorsContent">
<p:dataTable id="authorsTable"
value="#{bookAuthors.currentBook.lazyAuthors}"
var="author"
dynamic="true"
lazy="true"
paginator="true"
rows="5"
rowsPerPageTemplate="5,10,20"
paginatorTemplate="{PreviousPageLink} {CurrentPageReport} {NextPageLink} {RowsPerPageDropdown}">
<p:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:outputText value="#{author.name}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Details"/>
</f:facet>
<h:outputText value="#{author.details}"/>
</p:column>
</p:dataTable>
</p:outputPanel>
</h:form>
<p:outputPanel id="bookDialogContent">
<h:form prependId="false">
<p:dialog widgetVar="dlg" header="#{bookAuthors.currentBook.title}" id="bookAuthorsDialog" >
#{bookAuthors.currentBook.title}
<br/>
#{bookAuthors.currentBook.text}
</p:dialog>
</h:form>
</p:outputPanel>
</h:body>
</html>
Code: Select all
package controller;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import org.primefaces.model.LazyDataModel;
@SessionScoped
@ManagedBean
public class BookAuthors implements Serializable {
private List<Book> _books = new ArrayList<Book>();
private LazyDataModel<Book> _lazyBooks;
private Book _currentBook;
public BookAuthors() {
for (int i = 0, k = 0; i != 100; i++) {
List<Author> authors = new ArrayList<Author>();
for (int j = 0; j != 20; j++, k++)
authors.add(new Author("Author " + k, "Details for author " + k));
_books.add(new Book("Book " + i, "Info about book " + i, authors));
}
_lazyBooks = new LazyDataModel<Book>(_books.size()) {
@Override
public List<Book> fetchLazyData(int first, int pageSize) {
List<Book> lazyData = new ArrayList<Book>();
for (int i = 0; i != pageSize; i++)
lazyData.add(_books.get(first + i));
return lazyData;
}
};
}
public List<Book> getBooks() {
return _books;
}
public void setBooks(List<Book> books) {
_books = books;
}
public LazyDataModel<Book> getLazyBooks() {
return _lazyBooks;
}
public Book getCurrentBook() {
return _currentBook;
}
public void setCurrentBook(Book currentBook) {
_currentBook = currentBook;
}
}
Code: Select all
package controller;
import java.util.ArrayList;
import java.util.List;
import org.primefaces.model.LazyDataModel;
public class Book {
private String _title;
private String _text;
private List<Author> _authors;
private LazyDataModel<Author> _lazyAuthors;
public Book(String title, String text, List<Author> authors) {
_title = title;
_text = text;
_authors = authors;
_lazyAuthors = new LazyDataModel<Author>(_authors.size()) {
@Override
public List<Author> fetchLazyData(int first, int pageSize) {
List<Author> lazyData = new ArrayList<Author>();
for (int i = 0; i != pageSize; i++)
lazyData.add(_authors.get(first + i));
return lazyData;
}
};
}
public String getText() {
return _text;
}
public void setText(String text) {
_text = text;
}
public String getTitle() {
return _title;
}
public void setTitle(String title) {
_title = title;
}
public List<Author> getAuthors() {
return _authors;
}
public void setAuthors(List<Author> authors) {
_authors = authors;
}
public LazyDataModel<Author> getLazyAuthors() {
return _lazyAuthors;
}
@Override
public String toString() {
return getTitle();
}
}
Code: Select all
package controller;
public class Author {
private String _name;
private String _details;
public Author(String name, String details) {
_name = name;
_details = details;
}
public String getName() {
return _name;
}
public void setName(String name) {
_name = name;
}
public String getDetails() {
return _details;
}
public void setDetails(String details) {
_details = details;
}
@Override
public String toString() {
return getName();
}
}
Hi,
I was having some issues with datatable's selection and find this thread. I tried the example posted here, books and authors, with 2.1.RC1-SNAPSHOT.
I am wondering why getCurrentBook() is called so many times when clicking on a book row. I can't find the logic behind that behavior.
Besides, the "info" link doesn't work properly: dialog shows details for any book, not the expected one.
Any suggestion ?.
I was having some issues with datatable's selection and find this thread. I tried the example posted here, books and authors, with 2.1.RC1-SNAPSHOT.
I am wondering why getCurrentBook() is called so many times when clicking on a book row. I can't find the logic behind that behavior.
Besides, the "info" link doesn't work properly: dialog shows details for any book, not the expected one.
Any suggestion ?.
Hi callahan
Thank you for your sample - it works like expected but I cannot get my own code for layzy loading details to work. Maybe you can see the error?
Entity: Item2
Entity: Detail
EntityFacade: (abstract class)
EntityFacade: Item2
Controller class: ItemController
Finally the XHTML page:
When I select a row dataTable the the detailsPanel is refreshed but the setItem() nor the getLazyDetailModel() is never called in the ItemController until the entire form is submitted.
I have tried this code on 1.0.2 and 2.0.2 but the result remains the same.
Thank you for your sample - it works like expected but I cannot get my own code for layzy loading details to work. Maybe you can see the error?
Entity: Item2
Code: Select all
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package controller;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
@Entity
@Table(name = "ITEM2")
@NamedQueries({
@NamedQuery(name = "Item2.findAll", query = "SELECT i FROM Item2 i"),
@NamedQuery(name = "Item2.findById", query = "SELECT i FROM Item2 i WHERE i.id = :id"),
@NamedQuery(name = "Item2.findByName", query = "SELECT i FROM Item2 i WHERE i.name = :name")})
public class Item2 implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "ID", nullable = false)
private Long id;
@Basic(optional = false)
@Column(name = "NAME", nullable = false, length = 100)
private String name;
public Item2() {
}
public Item2(Long id) {
this.id = id;
}
public Item2(Long id, String name) {
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Item2)) {
return false;
}
Item2 other = (Item2) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "controller.Item2[id=" + id + "]";
}
}
Code: Select all
package controller;
public class Detail {
public int value;
public Detail(int value, int value2, long value3) {
this.value = value;
this.value2 = value2;
this.value3 = value3;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public int getValue2() {
return value2;
}
public void setValue2(int value2) {
this.value2 = value2;
}
public long getValue3() {
return value3;
}
public void setValue3(long value3) {
this.value3 = value3;
}
public int value2;
public long value3;
}
Code: Select all
package controller;
import java.util.List;
import javax.persistence.EntityManager;
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public void edit(T entity) {
getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
public List<T> findRange(int[] range) {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
javax.persistence.Query q = getEntityManager().createQuery(cq);
q.setMaxResults(range[1] - range[0]);
q.setFirstResult(range[0]);
return q.getResultList();
}
public int count() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.Query q = getEntityManager().createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
}
}
Code: Select all
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package controller;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
/**
*
* @author g95042
*/
@Stateless
public class Item2Facade extends AbstractFacade<Item2> {
@PersistenceContext(unitName = "WebApplication2PU")
private EntityManager em;
protected EntityManager getEntityManager() {
return em;
}
public Item2Facade() {
super(Item2.class);
}
}
Controller class: ItemController
Code: Select all
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package controller;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import org.primefaces.model.LazyDataModel;
@ManagedBean(name="item")
@SessionScoped
public class ItemController {
@EJB private controller.Item2Facade ejbFacade;
private Item2 item = null;
private Item2Facade getFacade() {
return ejbFacade;
}
private LazyDataModel<Item2> lazyModel = new LazyDataModel<Item2>()
{
@Override
public List<Item2> fetchLazyData(int first, int pageSize)
{
return getFacade().findRange(new int[]{first, first+pageSize});
}
@Override
public int getRowCount() {
return getFacade().count();
}
};
private LazyDataModel<Detail> lazyDetailModel = new LazyDataModel<Detail>(3)
{
@Override
public List<Detail> fetchLazyData(int first, int pageSize) {
List<Detail> list = new ArrayList<Detail>();
if (item != null)
{
Random r = new Random(78338);
list.add(new Detail(r.nextInt(), r.nextInt(), System.currentTimeMillis()));
list.add(new Detail(r.nextInt(), r.nextInt(), System.currentTimeMillis()));
list.add(new Detail(r.nextInt(), r.nextInt(), System.currentTimeMillis()));
}
return list;
}
};
public LazyDataModel<Detail> getLazyDetailModel() { return lazyDetailModel; }
public LazyDataModel<Item2> getLazyModel() { return lazyModel; }
//public void setLazyModel(LazyDataModel<Item2> lazyModel) { this.lazyModel = lazyModel; }
public Item2 getItem() { return item; }
public void setItem(Item2 item) { this.item = item; }
}
Code: Select all
<?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.prime.com.tr/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
</h:head>
<h:body>
<h1>Listing Item Items</h1>
<h:form prependId="false">
<p:dataTable value="#{item.lazyModel}" var="item1" id="dataTable" rows="5" paginator="true" lazy="true" dynamic="true" selectionMode="single" selection="#{item.item}"
rowsPerPageTemplate="5,10,20,50,100" paginatorTemplate="{PreviousPageLink} {CurrentPageReport} {NextPageLink} {RowsPerPageDropdown}" update="dataTable,detailPanel">
<p:column >
<f:facet name="header">
<h:outputText value="Id"/>
</f:facet>
<h:outputText value="#{item1.id}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:outputText value="#{item1.name}"/>
</p:column>
</p:dataTable>
<p:messages/>
<hr/>
<p:panel id="detailsPanel">
<p:dataTable id="detailTbl" value="#{item.lazyDetailModel}" var="detail" dynamic="true" lazy="true" rows="10" >
<p:column>
<f:facet name="header">
<h:outputText value="Value1"/>
</f:facet>
<h:outputText value="#{detail.value}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Value2"/>
</f:facet>
<h:outputText value="#{detail.value2}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Value3"/>
</f:facet>
<h:outputText value="#{detail.value3}"/>
</p:column>
</p:dataTable>
</p:panel>
</h:form>
</h:body>
</html>
I have tried this code on 1.0.2 and 2.0.2 but the result remains the same.
I don't know if it's the source of the problem, but there is a typo in the update attribute of the master-table.
update="dataTable,detailPanel" should be
update="dataTable,detailsPanel"
Why are you updating dataTable? Would updating only detailsPanel not be enough.
update="dataTable,detailPanel" should be
update="dataTable,detailsPanel"
Why are you updating dataTable? Would updating only detailsPanel not be enough.
-
- Information
-
Who is online
Users browsing this forum: No registered users and 19 guests