I use Prime Faces 6.2 to make a data table with checked column:
<p:dataTable id="#{prefix}List"
value="#{tickets}"
lazy="true"
paginator="true"
paginatorTemplate="{FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
currentPageReportTemplate="{startRecord}-{endRecord} из {totalRecords}"
rows="20"
rowKey="#{ticket.id}"
var="ticket"
emptyMessage="Записи в данной категории отсутствуют">
<p:ajax event="toggleSelect" listener="#{ticketForm.onAllSelect}" process="#this" partialSubmit="true" />
<p:ajax event="rowSelectCheckbox" listener="#{ticketForm.onSelect}" update=":protocolForm" />
<p:ajax event="rowUnselectCheckbox" listener="#{ticketForm.onUnselect}" update=":protocolForm" />
<p:ajax event="rowSelect" listener="#{ticketForm.onSelect}" update=":protocolForm" />
<p:ajax event="rowUnselect" listener="#{ticketForm.onUnselect}" update=":protocolForm" />
<p:column selectionMode="multiple" style="width:40px; text-align:center" />
More specifically, when a header checkbox is selected I want to receive all selected rows data on server-side and use IDs of each row. Also, there's logic that helps to resolve a goal of hidding/rendering a page button when at least one checkbox is selected.
For this purpose I need manualy intercept a row/checkbox selection event and record IDs from it when a button pushed, so I can't use selection attribute of dataTable using such logic.
On server-side I have several event-listeners:
private Set<AbstractMTSBUExportTicket> abstractMTSBUExportTickets = new HashSet<>();
public Set<AbstractMTSBUExportTicket> getAbstractMTSBUExportTickets() {
return abstractMTSBUExportTickets;
}
public void onSelect(SelectEvent event) {
abstractMTSBUExportTickets.add((AbstractMTSBUExportTicket) event.getObject());
}
public void onUnselect(UnselectEvent event) {
abstractMTSBUExportTickets.remove(event.getObject());
}
public void onAllSelect(ToggleSelectEvent event) {
// do smth
}
Unfortunately, ToggleSelectEvent has only information about data-table itself within.
None information about rows I couldn't find. Also I tried to add process="#this" partialSubmit="true" attributes but seems like they do different actions.
So, could you give me an example of how it's possible to retrieve such data from an event object?
Should I use another way to solve it? Thanks for your answers in advance.
You're use lazy dataTable and this doesn't stay the selection on page change.
You need set the selection param with a type of your collection
Implement getRowKey inside your LazyDataModel and remove rowKey="#{ticket.id}"
Selection with checkbox doesn't need selectionMode="multiple".
This param is only for multiple selection when click on the table row with CTRL is pressed
My sugestion is control your selected data manualy
XHTML file:
<p:dataTable id="#{prefix}List"
value="#{tickets}"
lazy="true"
paginator="true"
var="ticket"
selection="#{ticketForm.selectedTickets}"
emptyMessage="Записи в данной категории отсутствуют">
<p:ajax event="toggleSelect"
listener="#{ticketForm.onAllSelect}" partialSubmit="true"/>
<p:ajax event="rowSelectCheckbox"
listener="#{ticketForm.onSelect}" update=":protocolForm"/>
<p:ajax event="rowUnselectCheckbox"
listener="#{ticketForm.onUnselect}" update=":protocolForm"/>
<p:ajax event="rowSelect"
listener="#{ticketForm.onSelect}" update=":protocolForm"/>
<p:ajax event="rowUnselect"
listener="#{ticketForm.onUnselect}" update=":protocolForm"/>
<p:column selectionMode="multiple" style="width:40px; text-align:center" />
<!--other p:columns-->
</p:dataTable>
Managed bean:
public void onRowSelect(SelectEvent event) {
if (event != null && event.getObject() != null &&
event.getObject() instanceof Ticket) {
if (selectedTickets== null) {
selectedTickets= new ArrayList<Ticket>();
}
if (!selectedTickets.contains((Ticket) event.getObject())) {
selectedTickets.add((Ticket) event.getObject());
}
}
}
public void onRowUnselect(UnselectEvent event) {
if (event != null && event.getObject() != null &&
event.getObject() instanceof Ticket &&
selectedTickets != null && selectedTickets.contains((Ticket) event.getObject())) {
selectedTickets.remove((Ticket) event.getObject());
}
}
public void onAllRowsSelect(ToggleSelectEvent event) {
//This is the trick, you don't need receive a collection
if (event.isSelected()) {
selectedTickets = ticketService.getAllTickets();
} else {
selectedTickets = new ArrayList<Ticket>();
}
}
LazyDataModel implemention of getRowKey method:
public class LazyPragaModel extends LazyDataModel<Ticket> implements Serializable {
private TicketService ticketService;
private static final long serialVersionUID = 1L;
public LazyPragaModel(TicketService ticketService) {
this.ticketService= ticketService;
}
#Override
public Object getRowKey(Ticket ticket) {
return ticket!= null ? ticket.getId() : null;
}
#Override
public Praga getRowData(String rowKey) {
List<Ticket> tickets = (List<Ticket>) getWrappedData();
for (Ticket ticket: tickets) {
if (ticket.getId().toString().endsWith(rowKey)) {
return ticket;
}
}
return null;
}
#Override
public List<Ticket> load(int first, int pageSize, String sortField,
SortOrder sortOrder, Map<String, Object> filters) {
setRowCount(ticketService.countLazyRecords(filters).intValue());
List<Ticket> tickets = ticketService.listLazyRecords(first, pageSize,
sortField, sortOrder.name(), filters);
return tickets;
}
}
Sugestion for your service. Generic methods for lazy dataTables:
public List<T> listLazyRecords(int first, int pageSize, String sortField,
String sortOrder, Map<String, Object> filters) {
sortOrder = sortOrder != null ? sortOrder.contains("ASC") ? "ASC" :
sortOrder.contains("DESC") ? "DESC" : null : null;
String query = " FROM " + getType().getSimpleName() + " t " +
(filters.size() > 0 ? buildLazyFilters(filters) : "") +
(sortOrder != null ? " ORDER BY " + sortField + " " + sortOrder : "");
return getManager().createQuery(query, getType())
.setFirstResult(first).setMaxResults(pageSize).getResultList();
}
public Long countLazyRecords(Map<String, Object> filters) {
String query = "SELECT COUNT(x) FROM " + getType().getSimpleName() +
" x " + (filters.size() > 0 ? buildLazyFilters(filters) : "");
return getManager().createQuery(query).getSingleResult();
}
private String buildLazyFilters(Map<String, Object> filters) {
StringBuilder filterBuild = new StringBuilder("WHERE ");
for (Map.Entry<String, Object> filter : filters.entrySet()) {
if (filter.getValue().toString().chars().allMatch(Character::isDigit)) {
filterBuild.append("( " + filter.getKey() + " = " +
filter.getValue() + " OR ");
}
filterBuild.append(filter.getKey() + " LIKE '%" +
filter.getValue().toString() + "%'");
filterBuild.append(filter.getValue().toString().chars()
.allMatch(Character::isDigit) ? ") ": "");
filterBuild.append(!filters.values().toArray()[filters.size() - 1]
.equals(filter.getValue()) ? " AND " : "");
}
return filterBuild.toString();
}
I think you are missing some things on the datatable.
Showcase: https://www.primefaces.org/showcase/ui/data/datatable/selection.xhtml
You need to add selectionMode=multiple and a selection=collection to gather the selected rows like...
<p:dataTable id="multipleDT"
var="car"
value="#{dtSelectionView.cars4}"
selectionMode="multiple"
selection="#{dtSelectionView.selectedCars}"
rowKey="#{car.id}">
Whenever you select a row or row(s) the #{dtSelectionView.selectedCars} collection will be filled with the selected rows automatically.
Related
This question already has an answer here:
How and when should I load the model from database for JSF dataTable
(1 answer)
Closed 3 years ago.
I have developed a dynamic table which should refill table at every request, the same function is being performed by the code as follows:-
html
<h:form id="form">
<p:outputLabel value="Client: " />
<p:inputText id="inp" value="#{test.id}" />
<p:inputText id="inp1" value="#{test.title}" />
<p:commandButton value="Call List" action = "#{liveRangeService.LiveRangeServicesss(10)}"/>
<p:commandButton value="Call List" action = "#{liveRangeService.LiveRangeServicesss(20)}"/>
<p:dataTable var="result" id="tbl" widgetVar="dtlTBL"
value="#{liveRangeService.tableData}"
filteredValue="#{liveRangeService.filteredData}"
paginator="false"
scrollable="true" rowIndexVar="rowindex" scrollHeight="500"
scrollRows="50" liveScroll="true"
filterDelay="1100"
>
<p:ajax event="rowSelect" listener="#{test.onRowSelect(rowindex)}" />
<f:facet name="header">
<p:outputPanel layout="inline" styleClass="tabSpacer">
<h:outputText value="Global Filter:" />
<p:inputText id="globalFilter" onkeyup="PF('dtlTBL').filter()" style="width:150px;margin-left:10px;"/>
</p:outputPanel>
</f:facet>
<p:column width="50">
<f:facet name="header">
<h:outputText value="Sr." />
</f:facet>
<p:commandButton value="#{rowindex}" style="width: 49px" action="#{test.onRowSelect(rowindex)}"/>
</p:column>
<p:columns value="#{liveRangeService.tableHeaderNames}"
var="mycolHeader"
width="#{colIndex==0?'10%':colIndex==1?'70%':colIndex==2?'10%':colIndex==3?'10%':'0'}"
columnIndexVar="colIndex"
sortBy="#{result[mycolHeader]}"
filterBy="#{result[mycolHeader]}"
filterMatchMode="contains"
>
<f:facet name="header">
<h:outputText value="#{mycolHeader}" />
</f:facet>
<h:outputText value="#{result[mycolHeader]}" />
<br />
</p:columns>
</p:dataTable>
</h:form>
#ManagedBean(name="liveRangeService", eager = true)
#Dependent
public class LiveRangeService implements Serializable {
private static List< Map<String, String> > tableData;
public static List< Map<String, String> > filteredData;
private static List<String> tableHeaderNames;
private String tableColWidths;
public List<Map<String, String>> getTableData() {
return tableData;
}
public List<String> getTableHeaderNames() {
return tableHeaderNames;
}
public LiveRangeService() {
}
public static void LiveRangeServicesss(int noOfRows) {
tableData = new ArrayList< Map<String, String> >();
filteredData = new ArrayList< Map<String, String> >();
tableHeaderNames = new ArrayList<String>();
tableHeaderNames.add("ID");
tableHeaderNames.add("Title");
tableHeaderNames.add("Opn_Amt");
tableHeaderNames.add("Smr_Amt");
for (int i = 0; i < noOfRows; i++) {
Map<String, String> playlist = new HashMap<String, String>();
playlist.put("ID", "101000" + i);
playlist.put("Title", "Share Capital - Mr. " + i);
playlist.put("Opn_Amt", "0");
playlist.put("Smr_Amt", "0");
tableData.add(playlist);
}
filteredData=tableData;
System.out.println("Filled " + filteredData.size() + ", " + noOfRows);
String dlgTBL="form:tbl";
PrimeFaces.current().ajax().update(dlgTBL);
}
public String getTableColWidths() {
return tableColWidths;
}
public void setTableColWidths(String tableColWidths) {
this.tableColWidths = tableColWidths;
}
public List<Map<String, String>> getFilteredData() {
return filteredData;
}
public void setFilteredData(List<Map<String, String>> filteredData) {
this.filteredData = filteredData;
}
}
#ManagedBean(name="test")
#SessionScoped
public class Test implements Serializable {
public String id;
public String title;
public Test() {
id="1";
title="Testing";
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public void onRowSelect(int row) {
try {
String i="ID";
String t="Title";
String ci="id";
String ct="title";
this.getClass().getDeclaredField(ci).set(this, LiveRangeService.filteredData.get(row).get(i));
this.getClass().getDeclaredField(ct).set(this, LiveRangeService.filteredData.get(row).get(t));
PrimeFaces.current().ajax().update("form:inp");
PrimeFaces.current().ajax().update("form:inp1");
PrimeFaces.current().executeScript("PF('dlg').hide();");
} catch (Exception e) {
System.out.println("Error! " + e.getMessage() );
}
}
}
but the problem is that when the table is needed to be updated for other query, the call of function has to be done 2 times ie. i have placed two buttons, one pressing button 1, the table is populated with 10 rows and on pressing button 2, the table is populated with 20 rows. Each button is needed to be pressed two times to update the table.
Please advice.
i have just initialized the tables in Constructor, and all worked same as required.
#ManagedBean(name="liveRangeService")
#SessionScoped
public class LiveRangeService implements Serializable {
private List< Map<String, String> > tableData;
public List< Map<String, String> > filteredData;
private List<String> tableHeaderNames;
private String tableColWidths;
public List<Map<String, String>> getTableData() {
return tableData;
}
public List<String> getTableHeaderNames() {
return tableHeaderNames;
}
public LiveRangeService() {
tableData = new ArrayList< Map<String, String> >();
filteredData = new ArrayList< Map<String, String> >();
tableHeaderNames = new ArrayList<String>();
LiveRangeServicesss (-1, false);
System.out.println("in Constructor:");
}
public LiveRangeService(int noOfRows, boolean showDialogue) {
}
public void LiveRangeServicesss(int noOfRows, boolean showDialogue) {
tableData.clear();
tableHeaderNames.clear();
filteredData.clear();
tableHeaderNames.add("ID");
tableHeaderNames.add("Title");
tableHeaderNames.add("Opn_Amt");
tableHeaderNames.add("Smr_Amt");
for (int i = 0; i < noOfRows; i++) {
Map<String, String> playlist = new HashMap<String, String>();
playlist.put("ID", "101000" + noOfRows + i);
playlist.put("Title", "Share Capital - Mr. " + noOfRows + " - " + i);
playlist.put("Opn_Amt", "0");
playlist.put("Smr_Amt", "0");
tableData.add(playlist);
}
filteredData=tableData;
System.out.println("table size: " + tableData.size() + ", " + filteredData.size());
}
Using LazyDataModel does not display columns in the datatable.
I have implemented custom LazyDataModel and I have implemented load method init. However, when I pass the datamodel as a value to the datatable, the columns are not rendered/displayed. But when I pass it as a list, the columns are rendered/displayed.
My LazyDataModel class
public class SearchPmrLazyDataModel extends LazyBaseDataModel<SearchDTO> {
public SearchPmrLazyDataModel() {
}
public void setData() {
if (searchCriteria == null) {
searchCriteria = new PmrSearchCriteriaDTO();
}
setWrappedData(pmrService.searchPmr(searchCriteria, teamId));
}
#Override
public List<PmrSearchResultViewDTO> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
setData();
searchCriteria.setPageRequest(determinePage(first, pageSize));
List<PmrSearchResultViewDTO> data = this.cachedData;
// rowCount
int dataSize = data.size();
this.setRowCount(dataSize);
// paginate
if (dataSize > pageSize) {
try {
return data.subList(first, first + pageSize);
} catch (IndexOutOfBoundsException e) {
return data.subList(first, first + (dataSize % pageSize));
}
} else {
return data;
}
}
#Override
public void setRowIndex(int rowIndex) {
if (rowIndex == -1 || getPageSize() == 0) {
super.setRowIndex(-1);
}
else
super.setRowIndex(rowIndex % getPageSize());
}
#Override
public Object getRowKey(PmrSearchResultViewDTO obj) {
return obj.getId();
}
}
My bean
public LazyDataModel<SearchDTO> getCorresLazyDataModel(String selectedTabName, String selectedStateName, String selectedStateName2) {
//returns corresponding lazy data model according to a business logic
return getLazyDataModel(selectedTabName, selectedStateName, selectedStateName2);
}
My XHTML page
<p:dataTable
value="#{formBean.getCorresLazyDataModel(pmrStatusTab, pmrState, pmrState2)}"
var="pmr" id="pmrStatusResultTable#{pmrStatusTab}#{pmrState}"
widgetVar="pmrStatusResultTable#{pmrStatusTab}#{pmrState}"
style="overflow: auto; width: auto! important; table-width:fixed"
rows="10" rowKey="#{pmr.id}" rowStyleClass="odd, even"
reflow="true" scrollWidth="#{formBean.scrollWidth}"
scrollable="true" scrollRows="10" paginator="true" lazy="true"
selectionMode="single" selection="#{formBean.selectedPmr}">
<p:ajax event="rowSelect" process="#this"
listener="#{formBean.onRowSelect}" />
<p:columns value="#{formBean.columns}" var="column"
columnIndexVar="colIndex" sortBy="#{pmr[column.property]}"
sortable="true">
<f:facet name="header">
<h:outputText value="#{column.header}" />
</f:facet>
<h:outputText value="#{pmr[column.property]}" />
</p:columns>
</p:dataTable>
The columns are not rendered/displayed only if I pass datamodel directly. If I pass the value as list, they are displayed, is there anything which I am missing?
I've written (well, modified) a custom component for radio buttons appearing inside a datatable based on this article. I've modified it slightly for JSF 2.2 by using the #FacesRenderer and #FacesComponent tags and omitting the custom tag class. Everything works fine in my XHTML page
xmlns:custom="http://mynamespace"
...
<h:dataTable id="mySampleTable3"
value="#{myBackingBean.sampleTable3}"
var="item"
width="100%"
border="1"
first="0">
<f:facet name="header">
<h:panelGrid id="gridHeader3" columns="2" width="100%" >
<h:outputText id="outputText3"
value="Radios grouped in row(With our custom tag)"/>
</h:panelGrid>
</f:facet>
<h:column>
<f:facet name="header">
<h:outputText value="Emp Name" />
</f:facet>
<h:outputText id="empName" value="#{item.empName}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Excellent" />
</f:facet>
<custom:customradio id="myRadioId2"
name="myRadioRow"
value="#{item.radAns}"
itemValue="E" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Good" />
</f:facet>
<custom:customradio id="myRadioId3"
name="myRadioRow"
value="#{item.radAns}"
itemValue="G" />
</h:column>
...
</h:dataTable>
and the datatable of radio buttons work correctly (they are grouped by row). The problem arises when I use this component dynamically. So I have
HtmlPanelGrid radioGrid = (HtmlPanelGrid) getApplication()
.createComponent(HtmlPanelGrid.COMPONENT_TYPE);
...
UICustomSelectOneRadio customSelectOneRadio = (UICustomSelectOneRadio) getApplication().
createComponent(UICustomSelectOneRadio.COMPONENT_TYPE);
customSelectOneRadio.setId("rb_" + question.getQuestionId() + "_" + row + "_" + col);
customSelectOneRadio.setName("myRadioRow");
String binding = "#{" + beanName + "." + propName +
"[\"" + question.getQuestionId().toString() + "_" +
subQuestion.getId() + "\"]}";
ValueExpression ve = getExpressionFactory().
createValueExpression(getELContext(), binding, String.class);
customSelectOneRadio.setValueExpression("value", ve);
customSelectOneRadio.setItemValue(value);
radioGrid.getChildren().add(customSelectOneRadio);
Unfortunately, although the datatable is rendered, the radio buttons aren't. Blank columns appear. I was wondering if anyone knows if there is some method I should be overriding in my renderer. Mine looks like:
#FacesRenderer(componentFamily = UICustomSelectOneRadio.COMPONENT_FAMILY, rendererType = HTMLCustomSelectOneRadioRenderer.RENDERER_TYPE)
public class HTMLCustomSelectOneRadioRenderer extends Renderer {
public static final String RENDERER_TYPE = "com.myapp.jsf.renderers.HTMLCustomSelectOneRadioRenderer";
#Override
public void decode(FacesContext context, UIComponent component) {
if ((context == null) || (component == null)) {
throw new NullPointerException();
}
UICustomSelectOneRadio customSelectOneRadio;
if (component instanceof UICustomSelectOneRadio) {
customSelectOneRadio = (UICustomSelectOneRadio) component;
} else {
return;
}
Map map = context.getExternalContext().getRequestParameterMap();
String name = getName(customSelectOneRadio, context);
if (map.containsKey(name)) {
String value = (String) map.get(name);
if (value != null) {
setSubmittedValue(component, value);
}
}
}
private void setSubmittedValue(UIComponent component, Object obj) {
if (component instanceof UIInput) {
((UIInput) component).setSubmittedValue(obj);
}
}
private String getName(UICustomSelectOneRadio customSelectOneRadio,
FacesContext context) {
UIComponent parentUIComponent
= getParentDataTableFromHierarchy(customSelectOneRadio);
if (parentUIComponent == null) {
return customSelectOneRadio.getClientId(context);
} else {
if (customSelectOneRadio.getOverrideName() != null
&& customSelectOneRadio.getOverrideName().equals("true")) {
return customSelectOneRadio.getName();
} else {
String id = customSelectOneRadio.getClientId(context);
int lastIndexOfColon = id.lastIndexOf(":");
String partName = "";
if (lastIndexOfColon != -1) {
partName = id.substring(0, lastIndexOfColon + 1);
if (customSelectOneRadio.getName() == null) {
partName = partName + "generatedRad";
} else {
partName = partName + customSelectOneRadio.getName();
}
}
return partName;
}
}
}
private UIComponent getParentDataTableFromHierarchy(UIComponent uiComponent) {
if (uiComponent == null) {
return null;
}
if (uiComponent instanceof UIData) {
return uiComponent;
} else {
//try to find recursively in the Component tree hierarchy
return getParentDataTableFromHierarchy(uiComponent.getParent());
}
}
#Override
public void encodeEnd(FacesContext context, UIComponent component)
throws IOException {
if ((context == null) || (component == null)) {
throw new NullPointerException();
}
UICustomSelectOneRadio customSelectOneRadio
= (UICustomSelectOneRadio) component;
if (component.isRendered()) {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("input", component);
writer.writeAttribute("type", "radio", "type");
writer.writeAttribute("id", component.getClientId(context), "id");
writer.writeAttribute("name", getName(customSelectOneRadio, context), "name");
if (customSelectOneRadio.getStyleClass() != null && customSelectOneRadio.getStyleClass().trim().
length() > 0) {
writer.writeAttribute("class", customSelectOneRadio.getStyleClass().trim(), "class");
}
if (customSelectOneRadio.getStyle() != null && customSelectOneRadio.getStyle().trim().length() > 0) {
writer.writeAttribute("style", customSelectOneRadio.getStyle().trim(), "style");
}
...
if (customSelectOneRadio.getValue() != null
&& customSelectOneRadio.getValue().equals(customSelectOneRadio.getItemValue())) {
writer.writeAttribute("checked", "checked", "checked");
}
if (customSelectOneRadio.getItemLabel() != null) {
writer.write(customSelectOneRadio.getItemLabel());
}
writer.endElement("input");
}
}
}
To quickly summarise, this is working when I use a custom tag in an facelets/XHTML file, but not when I use it dynamically, e.g.
<h:panelGroup id="dynamicPanel" layout="block" binding="#{documentController.dynamicPanel}"/>
If anyone has any ideas on what I could be missing I'd be grateful.
Gotcha! It all revolved around changing the rendererType property. From the Renderer class above, you can see I had it set to my own, i.e.
public static final String RENDERER_TYPE = "com.myapp.jsf.renderers.HTMLCustomSelectOneRadioRenderer";
(1) I changed it to
public static final String RENDERER_TYPE = "javax.faces.Radio";
(2) I also changed my xxx.taglib.xml file to reflect this, e.g.
<namespace>http://mycomponents</namespace>
<tag>
<tag-name>customradio</tag-name>
<component>
<component-type>CustomRadio</component-type>
<renderer-type>javax.faces.Radio</renderer-type> /*<----- See Here */
</component>
</tag>
(3) But, here's the final step to note. I also had to create the following constructor in my UICustomSelectOneRadio component. It didn't work without this either.
public UICustomSelectOneRadio() {
this.setRendererType("javax.faces.Radio");
}
Remember - I extended my component from UIInput, so javax.faces.Text would have been set. Leaving my component family as "CustomRadio" was fine.
I'm still not 100% comfortable with renderer types etc., but for anyone who wants a little info, BalusC explains it well here.
I wanted to remove rows from the data table when the checkbox is ticked and remove button is pressed..
This is the datatable snippet :
<p:dataTable id="cartTable" lazy="true" scrollable="true"
scrollHeight="115" selection="#{Cart_Check.selectedItems}"
value="#{Cart_Check.cart}" var="cart" rowKey="#{cart.sheetno}"
style="widht:100%;margin-top:10%;margin-left:1%;margin-right:30px ;box-shadow: 10px 10px 25px #888888;">
<f:facet name="header">
Checkbox Based Selection
</f:facet>
<p:column selectionMode="multiple" style="width:2%">
</p:column>
//Here the columns are metion
<f:facet name="footer">
<p:commandButton id="viewButton" value="Remove" />
</f:facet>
</p:dataTable>
This is the backing bean
public class checkcart {
private int items;
private ArrayList<User_Cart> cart;
private ArrayList<User_Cart> selectedItems;
public checkcart() {
getvalues();
}
//getter and setter
public void getvalues() {
FacesContext context = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) context.getExternalContext()
.getSession(false);
System.out.println("Cart Request ::::" + session.getAttribute("regid"));
try {
Connection connection = BO_Connector.getConnection();
String sql = "Select * from cart_orderinfo where usrregno=?";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, (String) session.getAttribute("regid"));
ResultSet rs = ps.executeQuery();
cart = new ArrayList<>();
while (rs.next()) {
User_Cart user_cart = new User_Cart();
user_cart.setSheetno(rs.getString("sheetno"));
user_cart.setState_cd(rs.getString("state_cd"));
user_cart.setDist_cd(rs.getString("dist_cd"));
user_cart.setLicensetype(rs.getString("license_type"));
user_cart.setFormat(rs.getString("sheet_format"));
user_cart.setQuantity(rs.getInt("quantity"));
cart.add(user_cart);
}
} catch (Exception ex) {
System.out.println(ex);
}
}
}
and when i run this page i get the following error
datamodel must implement org.primefaces.model.selectabledatamodel when selection is enabled.
But when i remove the checkbox then their is no error but it is without a checkbox.
What to do and how to resolve the following error ..Kindly help..
I want something like this :
http://www.primefaces.org/showcase/ui/datatableRowSelectionRadioCheckbox.jsf
You just need to define ListDataModel as shown below,
public class SD_User_Cart extends ListDataModel<User_Cart> implements SelectableDataModel<User_Cart> {
public SD_User_Cart() {
}
public SD_User_Cart(List<User_Cart> data) {
super(data);
}
#Override
public User_Cart getRowData(String rowKey) {
//In a real app, a more efficient way like a query by rowKey should be implemented to deal with huge data
List<User_Cart> rows = (List<User_Cart>) getWrappedData();
for (User_Cart row : rows) {
if (row.getCartId.toString().equals(rowKey)) {//CartId is the primary key of your User_Cart
return row;
}
}
return null;
}
#Override
public Object getRowKey(User_Cart row) {
return row.get.getCartId();
}
}
Change your "cart" object into SD_User_Cart as shown below,
private SD_User_Cart cart;
Then define selection in p:datatable, and add a column as shown below,
<p:column selectionMode="multiple" style="width:18px"/>
Hope this helps:)
You need to define a your private ArrayList<User_Cart> selectedItems; data member in back class public class checkcart like this private User_Cart[] selectedItems; and give setter and getter method for the same it will work.
I had also faced same problem.
I have an editable table with dynamic columns. When I edit a row, all fields are displayed correctly. But when I click the 'save' icon, the value of my first element gets written to the wrong column.
Basically I have an undefined number of translation files and I want to display and edit them.
These files have content like
<entry key="contractlist_fleetmanager_status_ALL_STATUSES">All statuses</entry>
and for de
<entry key="contractlist_fleetmanager_status_ALL_STATUSES">Alle Zustände</entry>
Example I have 3 different translation files de, en and fr. The columns are as follows: en fr and de. But in the hashmap translation item, is get first de then some empty fields and then fr and en.
[de=Alle Zustände, null, null, null, null, null, null, null, null, fr=All statuses, en=All statuses, null, null, null, null, null]
When I debug and look into handleRowEdit, the selectedItem value is mixed up. The first element now has already the value of the en field in stead of the de field.
[de=All statuses, null, null, null, null, null, null, null, null, fr=All statuses, en=All statuses, null, null, null, null, null]
Is this caused by the fact that en is the first column (columns are: en fr de ) in my primefaces table?
How can I solve this?
This is my bean code
private TranslationItem selectedItem;
private List<TranslationItem> translationItems;
private List<ColumnModel> columns = new ArrayList<ColumnModel>();
public Translation() {
createDynamicColumns();
}
public String handleRowEdit(TranslationItem selectedItem) throws IOException {
setSelectedItem(selectedItem);
getLog().debug("rowedit");
return "";
}
public List<ColumnModel> getColumns() {
return columns;
}
public List<TranslationItem> getTranslationItems() throws IOException {
if (translationItems == null) {
translationItems = new ArrayList<TranslationItem>();
Properties[] props = new Properties[localeItems().length];
int i = 0;
for (String locale : localeItems()) {
FileInputStream in = new FileInputStream(SiteConfig.getInstance().getDefaultConfigPath() + File.separator
+ "language_" + locale + ".xml");
props[i] = new Properties();
props[i].loadFromXML(in);
in.close();
i++;
}
Enumeration<Object> keys = props[0].keys();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
i = 0;
Map<String, String> value = new LinkedHashMap<String, String>() {
#Override
public String put(String key, String value) {
return super.put(key, value);
}
};
for (String locale : localeItems()) {
value.put(locale, props[i].getProperty(key));
i++;
}
translationItems.add(new TranslationItem(key, value));
}
}
return translationItems;
}
public void createDynamicColumns() {
String columnTemplate = "";
for (String locale : localeItems()) {
columnTemplate += locale + " ";
}
String[] columnKeys = columnTemplate.split(" ");
columns.clear();
for (String columnKey : columnKeys) {
columns.add(new ColumnModel(columnKey, columnKey));
}
}
//inner class TranslationItem
public class TranslationItem {
private String key;
private Map<String, String> value;
public TranslationItem() {
}
public TranslationItem(String key, Map<String, String> value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Map<String, String> getValue() {
return value;
}
public void setValue(Map<String, String> value) {
this.value = value;
}
public String getValueLocale(String locale) {
return value.get(locale);
}
}
//inner class ColumnModel
static public class ColumnModel implements Serializable {
private String header;
private String property;
public ColumnModel(String header, String property) {
this.header = header;
this.property = property;
}
public String getHeader() {
return header;
}
public String getProperty() {
return property;
}
}
And this is my jsf code
<p:dataTable id="translationtable" styleClass="ptable100" var="translation" value="#{adminTranslation.translationItems}" width="100%" height="200" widgetVar="translation"
emptyMessage="#{msg.all_lists_no_records_found}" editable="true" rowKey="#{translation.key}" rowIndexVar="rowIndex" selection="#{adminTranslation.selectedItem}" selectionMode="single"
resizableColumns="true" sortMode="multiple"
paginator="true" rows="20" rowsPerPageTemplate="5,10,20,50,100" paginatorTemplate="{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} #{msg.all_lists_numberOfRowsDisplayed_label} {RowsPerPageDropdown}"
>
<p:ajax event="rowEdit" listener="#{adminTranslation.onEdit}" update="translationtable" />
<p:columns value="#{adminTranslation.columns}" headerText="#{column.header}" var="column" columnIndexVar="colIndex"
sortBy="#{translation.value[column.property]}" filterBy="#{translation.value[column.property]}" filterMatchMode="contains"
filterPosition="top" filterStyle="float:right;width: 200px;" styleClass="ui-editable-column">
<p:column >
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{translation.value[column.property]}"/></f:facet>
<f:facet name="input"><h:inputText value="#{translation.value[column.property]}" styleClass="input ilarge" /></f:facet>
</p:cellEditor>
</p:column>
</p:columns>
<p:column >
<p:commandLink id="rowEditLink" actionListener="#{adminTranslation.handleRowEdit(translation)}" ajax="true" >
<p:rowEditor id="edit"/>
</p:commandLink>
</p:column>
</p:dataTable>
I use primefaces 3.2 on tomcat 7