I have a primefaces datatable below:
<p:dataTable id="table_lista_grupos" value="#{grupoClasseBean.gldm}" var="item"
widgetVar="lista_grupos" rowKey="#{item.codigo}" paginator="true" rows="10"
styleClass="panelGrande" paginatorPosition="bottom" sortMode="multiple"
filteredValue="#{grupoClasseBean.listaGruposFiltrados}" rowHover="true"
resizeMode="expand" selectionMode="single" lazy="true" rowsPerPageTemplate="10,20,30"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}" >
and I need implementing a lazy load,
I followed the documentation and I created the class below:
public class GrupoLazyDataModel extends LazyDataModel<Grupo>{
private static final long serialVersionUID = 1L;
private List<Grupo> datasource;
public GrupoLazyDataModel(List<Grupo> datasource) {
this.datasource = datasource;
setRowCount(datasource.size());
}
#Override
public List<Grupo> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
return new ArrayList<Grupo>();
}
}
and I call this class in my ManagedBean
#Named
#RequestScoped
public class GrupoClasseBean implements Serializable {
private LazyDataModel<Grupo> gldm;
#PostConstruct
public void init() {
Map<TipoParametro, Object> params = new HashMap<>();
params.put(TipoParametro.TIPO, tipo);
listaGrupos = (List<Grupo>) rule.list(0, 100, params);
gldm = new GrupoLazyDataModel(listaGrupos);
}
}
but when I execute my software, I receive the error message:
Receiver class br.gov.sp.sefaz.siafem.cm.ui.grpcls.GrupoLazyDataModel does not define or inherit an implementation of the resolved method abstract load(IILjava/util/Map;Ljava/util/Map;)Ljava/util/List; of abstract class org.primefaces.model.LazyDataModel.
My environment is primefaces 5.3, tomcat 9, jdk 1.8, netbeans 12.2, database derby
I solved this issue updating the primefaces version, from 5.3 to 10.0
Related
I have created a dynamic datatable in primefaces and tried to filter the columns but the filter is not working, help me please.
I have created a table where columns headers and values that is properties are rendered dynamically and iterated by the var of a datatable.
primefaces code below
<p:dataTable var="sales" value="#{customermisreportbean.custList}"
paginator="#{customermisreportbean.pagenatorActive}" rows="#{customermisreportbean.pagenatorActive?10:0}"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="5,10,15" id="misreport" lazy="true"
filteredValue="#{customermisreportbean.filterval}" widgetVar="mistable">
<p:columns value="#{customermisreportbean.reportcolumns}"
var="column" filterBy="#{sales[column.property]}" columnIndexVar="colindex" headerText="#{column.header}">
<h:outputText value="#{sales[column.property]}"
styleClass="#{column.align}" />
</p:columns>
</p:dataTable>
Below is the bean class
public class columns implements Serializable{
private String header="";
private String property="";
private String align="";
public columns(String header, String property,String align) {
this.header = header;
this.property = property;
this.align=align;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
public String getAlign() {
return align;
}
public void setAlign(String align) {
this.align = align;
}
}
I've actually found quite a bit on this in various different forums, but none of them appear to have worked for me. My problem isn't even that complicated, but I can't figure out why it's not working. I've set up my datatable so that it's editable and set the editMode="cell". I set up the ajax event and it fires, but the new and old values are always null.
When I'm finished editing a cell and go to the next cell, the cell goes back to the old value. When I click back into it, it shows the new value. Both the outputLabel and inputText tags use the exact same variable, but they are not showing the same value. I've tried manually updating the table manually through the method call as well and that does nothing. Also tried putting a p:ajax tag inside the inputText tag to update the table and that didn't work either.
Here's my JSF code:
<p:dataTable id="dynamicTable" value="#{column.values}" var="value" editable="true" editMode="cell">
<p:ajax event="cellEdit" listener="bean.updateCell" immediate="true" update=":dynamicTable"/>
<p:columns value="#{bean.columns}" var="column">
<f:facet name="header">
<p:outputLabel value="#{column.name}"/>
</f:facet>
<p:cellEditor>
<f:facet name="output"><p:outputLabel value="#{value}"/></f:facet>
<f:facet name="input"><p:inputText value="#{value}"/></f:facet>
</p:cellEditor>
</p:columns>
</p:dataTable>
Here's my bean:
#ManagedBean(name = "bean")
#ViewScoped
public class Bean implements Serializable {
private ArrayList<Column> columns;
public ArrayList<Column> getColumns(){
return columns;
}
public void setColumns(ArrayList<Column> columns){
this.columns = columns;
}
#PostConstruct
void init(){
columns = new ArrayList<>();
Column column = new Column();
column.setName("Acronym");
ArrayList<String> values = new ArrayList<>();
values.add("KFC");
values.add("TTYL");
values.add("BRB");
column.setValues(values);
columns.add(column);
column = new Column();
column.setName("Meaning");
values = new ArrayList<>();
values.add("Kentuky Fried Chicken");
values.add("Talk to you later");
values.add("Be right back");
column.setValues(values);
columns.add(column);
}
public void updateCell(CellEditEvent event){
System.out.println((String) event.getNewValue();
}
}
And my Column class:
public class Column{
private ArrayList<String> values;
private String name;
public ArrayList<String> getValues(){
return values;
}
public void setValues(ArrayList<String> values){
this.values = values;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
I rewrote the code to not include sensitive information and renamed variables, so if I'm missing something it's possible that I already have it in my code, but have accidentally removed it.
It turns out the way I was doing the p:columns tag was incorrect. After I made the following changes my problem was solved.
I've made an additional class called TableRow with various String objects to signify the columns to be used. Here's the new code:
JSF:
<p:dataTable id="dynamicTable" value="#{bean.tblRows}" var="row" editable="true" editMode="cell">
<p:columns value="#{bean.columns}" var="column">
<f:facet name="header">
<p:outputLabel value="#{column.name}"/>
</f:facet>
<p:cellEditor>
<f:facet name="output"><p:outputLabel value="#{row[column.variable]}"/></f:facet>
<f:facet name="output"><p:inputText value="#{row[column.variable]}"/></f:facet>
</p:cellEditor>
</p:columns>
</p:dataTable>
Bean:
#ManagedBean (name = "bean")
#ViewScoped
public class Bean implements Serializable {
private ArrayList<TableRow> tblRows;
private ArrayList<Column> columns;
public ArrayList<TableRow> getTblRows(){
return tblRows;
}
public void setTblRows(ArrayList<TableRow> tblRows){
this.tblRows = tblRows;
}
public ArrayList<Column> getColumns(){
return columns;
}
public void setColumns(ArrayList<Column> columns){
this.columns = columns;
}
#PostConstruct
void init(){
columns = new ArrayList<>();
columns.add(new Column("Acronym", "col1");
columns.add(new Column("Meaning", "col2");
tblRows = new ArrayList<>();
tblRows.add(new TableRow("KFC", "Kentuky Fried Chicken"));
tblRows.add(new TableRow("TTYL", "Talk to you later"));
tblRows.add(new TableRow("BRB", "Be right back"));
}
}
TableRow Class:
public class TableRow {
private String col1;
private String col2;
public TableRow(String col1, String col2){
this.col1 = col1;
this.col2 = col2;
}
public String getCol1(){
return col1;
}
public void setCol1(String col1){
this.col1 = col1;
}
public String getCol2(){
return col2;
}
public void setCol2(String col2){
this.col2 = col2;
}
}
Column Class:
public class Column {
private String name;
private String variable;
public Column(String name, String variable){
this.name = name;
this.variable = variable;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public String getVariable(){
return variable;
}
public void setVariable(String variable){
this.variable = variable;
}
}
The reason why I did "col1" and "col2" instead of give distinct variable names is that the user can choose the column header names so I won't know what to name the variables ahead of time. I was wondering if anyone would like to enlighten me how I could handle this dynamically a little better. When the bean is initialized I don't know how many columns there are going to be or what the column names are going to be.
I'm using primefaces tabView component. Each tag has its own managed bean and .xhtml page referencing that bean.
The problem is that EACH TIME tab is clicked, fresh data should be fetched from database (not just the first time), in other words data should be refreshed.
My beans are #ViewScoped. I don't want to use #RequestScoped because I have very dynamic ajax-enabled pages.
My solution currently looks like this:
I have managed bean for the main page with tabView component (MainBean) which contains method for handling tabChange event.
That bean also has references to beans assigned to each tab (TabBean1, TabBean2) so that right bean could be refreshed according to the id of the chosen tab.
MainBean:
#ManagedBean(name = "mainBean")
#ViewScoped
public class MainBean implements Serializable {
private static final long serialVersionUID = 1L;
#ManagedProperty(value = "#{tabBean1}")
private TabBean1 tabBean1;
#ManagedProperty(value = "#{tabBean2}")
private TabBean2 tabBean2;
public void onTabChange(TabChangeEvent event) {
String id = event.getTab().getId();
if ("tab1Id".equals(id)) {
tabBean1.init();
} else if ("tab2Id".equals(id)) {
tabBean2.init();
}
}
public TabBean1 getTabBean1() {
return tabBean1;
}
public void setTabBean1(TabBean1 tabBean1) {
this.tabBean1 = tabBean1;
}
public TabBean2 getTabBean2() {
return tabBean2;
}
public void setTabBean2(TabBean2 tabBean2) {
this.tabBean2 = tabBean2;
}
}
TabBean1:
#ManagedBean(name = "tabBean1")
#ViewScoped
public class TabBean1 implements Serializable {
private static final long serialVersionUID = 1L;
private List<String> data;
#PostConstruct
public void init() {
// refresh data
}
}
TabBean2:
#ManagedBean(name = "tabBean2")
#ViewScoped
public class TabBean2 implements Serializable {
private static final long serialVersionUID = 1L;
private List<String> data;
#PostConstruct
public void init() {
// refresh data
}
}
Relevant part od main.xhtml:
<p:tabView id="tabViewID" cache="false" dynamic="true">
<p:ajax event="tabChange" listener="#{mainBean.onTabChange}" />
<p:tab title="Tab 1" id="tab1Id">
<ui:include src="tab1Page.xhtml" />
</p:tab>
<p:tab title="Tab 2" id="tab2Id">
<ui:include src="tab2Page.xhtml" />
</p:tab>
</p:tabView>
Problem with this approach is:
when MainBean is constructed, all its managed properties are constructed also. This is a huge problem because #PostConstruct method of each bean fetches some data from database and everything is just too slow beacuse all beans are initialized when only one should really be initialized (the one assigned to selected tab)
on first page load, init() method is called twice for TabBean1, once because of #PostConstruct and once because it is assigned to tabChange event (first tab is selected by default)
My question is:
how can I 'refresh bean data' when corresponding tab is clicked?
how can I do that dynamically, just for the chosen tab (initially and every click after)?
I would really appreciate your suggestions. Thanks!
I'm using Primefaces 6.0, JSF 2.2.
I have the list with very data. I want to show data in Primeface data table with lazy loading ability. now I show data normal in data Table, but it is slow.
How can use lazy loading ability?
XHTML File :
<ui:composition template="template.xhtml">
<ui:define name="content">
<p:panel id="pnlLogInformationPage">
<h:form id="logInformation">
<div class="contentContainer-full-left">
<p:dataTable var="log" value="#{logInformationMB.logInformationList}" id="logTable"
width="100%" liveResize="true">
<p:column headerText="ID" sortBy="Id">
<h:outputText value="#{logInformation.Id}" />
</p:column>
<p:column headerText="Name" sortBy="Name">
<h:outputText value="#{logInformation.Name}" />
</p:column>
</p:dataTable>
</div>
</h:form>
</p:panel>
</ui:define>
ManageBean File:
#ManagedBean(name = "logInformationMB")
#ViewScoped
public class LogManagedBean implements Serializable {
#PostConstruct
public void initComponents() {
loadLogInformation();
}
public List<LogInformationDTO> getLogInformationList() {
return logInformationList;
}
public void setLogInformationList(final List<LogInformationDTO> pLogInformationList) {
logInformationList = pLogInformationList;
}
public void loadLoagInformation(final ComponentSystemEvent event) {
setLogLInformationlist(getLogInformationList();
}
public void loadInformationProtokolle() {
loadInformationProtokolle(null);
}
public List<LogInformationDTO> getLogInformation() {
final List<LogInformationDTO> lcResult = new ArrayList<LogInformationDTO>();
....
return lcResult;
}
}
According to your code, you didn't use lazyloading. you just get all your datas.
It will be slow when your data is too big.
See my steps below:
1- Instead of using #{logInformationMB.logInformationList}, you need to create new class which extend LazyDataModel class and create a service that can get data page by page.
public class LogInformationDataModel extends LazyDataModel<LogInformationDTO> {
private List<LogInformationDTO> logInformationList;
private LogInformationService logInformationService = new LogInformationService();
#Override
public List<LogInformationDTO> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
// TODO implement sort
setRowCount(logInformationService.count(filters));
logInformationList = logInformationService.list(first / pageSize, pageSize, sortField, sort, filters);
return logInformationList;
}
#Override
public LogInformationDTO getRowData(String rowKey) {
for(LogInformationDTO logInformation : logInformationList) {
if(logInformation.getId().equals(rowKey))
return logInformation;
}
return null;
}
#Override
public Object getRowKey(LogInformationDTO logInformation) {
return logInformation.getId();
}
}
2- Register data model in your Manage bean
#ManagedBean(name = "logInformationMB")
#ViewScoped
public class LogManagedBean implements Serializable {
private LogInformationDataModel dataModel = new LogInformationDataModel();
public LogInformationDataModel getDataModel() {
return dataModel;
}
}
3- Add lazy attribe (lazy="true") to your p:dataTable and using pagination
<p:dataTable var="log" value="#{logInformationMB.dataModel}" var="logInformation" id="logTable"
width="100%"
lazy="true"
paginator="true"
paginatorPosition="bottom"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="10,50,100"
>
<p:column headerText="ID" sortBy="Id">
<h:outputText value="#{logInformation.Id}" />
</p:column>
<p:column headerText="Name" sortBy="Name">
<h:outputText value="#{logInformation.Name}" />
</p:column>
</p:dataTable>
I Hope my answer could solve your issue.
Below is the link you can check :
Primefaces lazydatamodel
I am using primefaces 3.2 and mojarra 2.1.7 with jboss 6.1. I am trying to build a lazy loading datatable. In one of the datatable columns I have a commandlink to call a edit method. If my bean is conversation scoped, the edit method is not called. If it is view scoped then it gets called. I cant have a conversation scoped bean to work with a lazy loading datatable?
#Named("userBean")
#Stateful
#ConversationScoped
#LoggedIn
public class UserBean implements Serializable, UserBeanLocal {
private static final long serialVersionUID = 1L;
#Inject
private Conversation conversation;
#EJB
private UserManagerBeanLocal userController;
#Inject
private transient FacesContext context;
private User user;
private LazyUserDataModel lazyModel;
public UserBean() {
user = new User();
}
#Override
#PostConstruct
public void createLazyDataModel() {
setLazyModel(new LazyUserDataModel(userController));
}
#Override
#PrePassivate
public void ejbPassivate(){
context = null;
}
#Override
#PostActivate
public void ejbActivate() {
}
#Override
public String create() {
this.conversation.begin();
return "create";
}
#Override
public String edit()
{
System.out.println("editing user");
return "create";
}
}
and
<h:form>
....
<p:dataTable id="userTable" var="usr" value="#{userBean.lazyModel}"
paginator="true"
paginatorTemplate="{FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15" paginatorPosition="bottom" rows="10"
currentPageReportTemplate="{currentPage} de {totalPages}">
<p:column headerText="Username">
<h:outputText value="#{usr.name}" />
</p:column>
<p:column>
<p:commandLink value="Edit" action="#{userBean.edit}" actionListener="#{userBean.update}" update="userTable" />
</p:column>
</p:dataTable>
</h:form>
Can anybody help?
Thanks
Kelly
Well, it certainly should work. There is nothing obviously wrong with your code, but I suspect from the snippet you are providing that you have some "try and error" history...;-)
Try to debug the conversation and see which conversation is addressed (and when). Are you propagating the conversation-id correctly?
When you write ViewScoped works - did you include Seam 3 for bridging JSF-scopes to CDI, or can it be that you are mixing JSF and CDI scopes?
And: Don't put any EJB code in the constructor as you don't have any guarantee when (and how often) this will be called. Better to use #PostConstruct instead.
My problem was that I was not propagating the conversation id correctly.