Sheet fills a need that the PrimeFaces DataTable with in-cell editing does not fill. It handles a large amount of data and edits single cells without submitting the entire sheet. Based on Handsontable by Handsoncode.
Fixed columns and rows, custom cell styling, sorting, filtering and per-cell validation. Enter "abc" into the Price column, which expects a BigDecimal.
Sheet data can be exported with p:dataExporter just like a DataTable. Use the toolbar buttons to export CSV or XML; the exporter respects the current sort and filter state.
Create columns dynamically and render their style and other attributes from backing beans. Also shows how to customize the Handsontable instance with updateSettings and the extender JavaScript.
<style>
.positive {
color: Green !important;
}
.negative {
color: Red !important;
}
.password {
color: DarkViolet !important;
}
.cell-blue {
color: blue;
}
.cell-orange {
color: darkorange;
}
</style>
<div class="card">
<h5>Basic Usage</h5>
<p>Fixed columns and rows, custom cell styling, sorting, filtering and per-cell validation. Enter "abc" into the Price column, which expects a <code>BigDecimal</code>.</p>
<h:form id="formBasicUsage">
<p:messages id="messages" showSummary="true" showDetail="true"/>
<p:importEnum type="org.primefaces.extensions.showcase.model.sheet.AssetType" var="AssetType"/>
<p:importEnum type="org.primefaces.extensions.showcase.model.sheet.PlatformType" var="PlatformType"/>
<pe:sheet id="sheet" widgetVar="sheetBasicWidget" value="#{sheetController.assets}" var="row"
height="400" rowKey="#{row.assetId}" fixedCols="2" fixedRows="3" showRowHeaders="true"
resizableCols="true" resizableRows="true" filteredValue="#{sheetController.filteredAssets}"
sortBy="#{row.assetId}" sortOrder="ascending" readOnly="false" rowStyleClass="#{row.purchasePrice gt 0 ? 'positive' : 'negative'}">
<p:ajax event="change" listener="#{sheetController.cellChangeEvent}" update="messages"/>
<f:facet name="header">
<h:outputText value="Assets"/>
</f:facet>
<f:facet name="footer">
<h:outputText id="footer" value="#{sheetController.filteredAssets.size()} Records"/>
</f:facet>
<pe:sheetcolumn headerText="Id (read-only)"
readOnly="true"
value="#{row.assetId}"
sortBy="#{row.assetId}"
colWidth="150"
filterBy="#{row.assetId}"/>
<pe:sheetcolumn headerText="Icon"
readOnly="true"
styleClass="text-center"
value="#{row.icon}"
colWidth="80"/>
<pe:sheetcolumn headerText="Type" value="#{row.assetType}" colWidth="100"
sortBy="#{row.assetType}" filterBy="#{row.assetType}"
filterOptions="#{sheetOptionProducer.assetTypes}"
colType="dropdown"
selectItems="#{AssetType.ALL_VALUES}"/>
<pe:sheetcolumn headerText="Platform" value="#{row.platform}" colWidth="100"
sortBy="#{row.platform}" filterBy="#{row.platform}"
filterOptions="#{sheetOptionProducer.platformTypes}"
colType="autocomplete"
selectItems="#{PlatformType.ALL_VALUES}"
autoCompleteStrict="false"
autoCompleteVisibleRows="4"/>
<pe:sheetcolumn headerText="Arch" value="#{row.platformArch}" readOnly="true"
colWidth="100" sortBy="#{row.platformArch}"
filterBy="#{row.platformArch}"
filterOptions="#{sheetOptionProducer.archTypes}"/>
<pe:sheetcolumn headerText="Active" value="#{row.active}" colWidth="60" colType="checkbox"/>
<pe:sheetcolumn headerText="Price" value="#{row.purchasePrice}" colWidth="100"
styleClass="htRight #{row.purchasePrice gt 0 ? 'positive' : 'negative'}"
colType="numeric"
numericLocale="de-DE"
numericPattern="$0,0.00"
required="true"
requiredMessage="Price is required!">
<f:converter converterId="jakarta.faces.BigDecimal"/>
</pe:sheetcolumn>
<pe:sheetcolumn headerText="Password" value="#{row.password}" colWidth="100" styleClass="password"
colType="password"
passwordHashSymbol="*"
passwordHashLength="8"/>
<pe:sheetcolumn headerText="Date" value="#{row.purchaseDate}" colWidth="110"
sortBy="#{row.purchaseDate}"
styleClass="htCenter"
colType="date"
dateFormat="YYYY-MM-DD">
<f:convertDateTime type="date" pattern="yyyy-MM-dd"/>
</pe:sheetcolumn>
<pe:sheetcolumn headerText="Time" value="#{row.purchaseTime}" colWidth="110"
sortBy="#{row.purchaseTime}"
styleClass="htCenter"
colType="time"
timeFormat="h:mm:ss a">
<f:convertDateTime type="time" pattern="h:mm:ss a"/>
</pe:sheetcolumn>
<pe:sheetcolumn headerText="Value 1" value="#{row.value1}" colWidth="100" colType="numeric"/>
<pe:sheetcolumn headerText="Value 2" value="#{row.value2}" colWidth="100" colType="numeric"/>
<pe:sheetcolumn headerText="Value 3" value="#{row.value3}" colWidth="100" colType="numeric"/>
<pe:sheetcolumn headerText="Value 4" value="#{row.value4}" colWidth="100" colType="numeric"/>
<pe:sheetcolumn headerText="Value 5" value="#{row.value5}" colWidth="100" colType="numeric"/>
<pe:sheetcolumn headerText="Value 6" value="#{row.value6}" colWidth="100" colType="numeric"/>
<pe:sheetcolumn headerText="Value 7" value="#{row.value7}" colWidth="100" colType="numeric"/>
<pe:sheetcolumn headerText="Value 8" value="#{row.value8}" colWidth="100" colType="numeric"/>
<pe:sheetcolumn headerText="Value 9" value="#{row.value9}" colWidth="100" colType="numeric"/>
<pe:sheetcolumn headerText="Value 10" value="#{row.value10}" colWidth="100" colType="numeric"/>
</pe:sheet>
</h:form>
</div>
<div class="card">
<h5>Data Export</h5>
<p>Sheet data can be exported with <code>p:dataExporter</code> just like a DataTable. Use the toolbar buttons to export CSV or XML; the exporter respects the current sort and filter state.</p>
<h:form id="formDataExport">
<p:importEnum type="org.primefaces.extensions.showcase.model.sheet.AssetType" var="AssetType"/>
<p:importEnum type="org.primefaces.extensions.showcase.model.sheet.PlatformType" var="PlatformType"/>
<p:toolbar>
<p:toolbarGroup align="left">
<p:commandButton icon="pi pi-file" value="CSV">
<p:dataExporter type="csv" target="sheet" fileName="sheet-export"/>
</p:commandButton>
<p:commandButton icon="pi pi-file" value="XML">
<p:dataExporter type="xml" target="sheet" fileName="sheet-export"/>
</p:commandButton>
</p:toolbarGroup>
</p:toolbar>
<pe:sheet id="sheet" widgetVar="sheetExportWidget" value="#{sheetExportController.assets}" var="row"
height="400" rowKey="#{row.assetId}" fixedCols="2" showRowHeaders="true"
resizableCols="true" filteredValue="#{sheetExportController.filteredAssets}"
sortBy="#{row.assetId}" sortOrder="ascending">
<f:facet name="header">
<h:outputText value="Assets"/>
</f:facet>
<f:facet name="footer">
<h:outputText id="footer" value="#{sheetExportController.filteredAssets.size()} Records"/>
</f:facet>
<pe:sheetcolumn headerText="Id" readOnly="true" value="#{row.assetId}"
sortBy="#{row.assetId}" colWidth="100"/>
<pe:sheetcolumn headerText="Type" value="#{row.assetType}" colWidth="120"
sortBy="#{row.assetType}" filterBy="#{row.assetType}"
colType="dropdown" selectItems="#{AssetType.ALL_VALUES}"/>
<pe:sheetcolumn headerText="Platform" value="#{row.platform}" colWidth="120"
sortBy="#{row.platform}" filterBy="#{row.platform}"
colType="autocomplete" selectItems="#{PlatformType.ALL_VALUES}"
autoCompleteStrict="false" autoCompleteVisibleRows="4"/>
<pe:sheetcolumn headerText="Active" value="#{row.active}" colWidth="80" colType="checkbox"/>
<pe:sheetcolumn headerText="Price" value="#{row.purchasePrice}" colWidth="120"
colType="numeric" numericLocale="de-DE" numericPattern="$0,0.00">
<f:converter converterId="jakarta.faces.BigDecimal"/>
</pe:sheetcolumn>
<pe:sheetcolumn headerText="Date" value="#{row.purchaseDate}" colWidth="120"
sortBy="#{row.purchaseDate}" colType="date" dateFormat="YYYY-MM-DD">
<f:convertDateTime type="date" pattern="yyyy-MM-dd"/>
</pe:sheetcolumn>
</pe:sheet>
</h:form>
</div>
<div class="card">
<h5>Dynamic Columns</h5>
<p>Create columns dynamically and render their style and other attributes from backing beans. Also shows how to customize the Handsontable instance with <code>updateSettings</code> and the <code>extender</code> JavaScript.</p>
<h:form id="formDynamicColumns">
<pe:sheet id="sheet" value="#{sheetDynamicController.sheetRows}" var="row" height="400" rowKey="#{row.id}"
showRowHeaders="true" sortBy="#{row.id}" sortOrder="ascending" width="1000"
widgetVar="sheetDynamicWidget" filteredValue="#{sheetDynamicController.filteredSheetRows}"
extender="sheetExtender">
<f:facet name="header">
<h:outputText value="Dynamic Columns"/>
</f:facet>
<pe:sheetcolumn headerText="Id (readOnly)" readOnly="true" value="#{row.id}" colWidth="150"/>
<c:forEach items="#{sheetDynamicController.hoursOfDay}" var="hourOfDay" varStatus="status">
<pe:sheetcolumn styleClass="htRight #{row.cells[status.index].style}"
headerText="#{hourOfDay}"
value="#{row.cells[status.index].value}"
readonlyCell="#{row.readOnly}"
colType="numeric">
<f:converter converterId="jakarta.faces.Integer"/>
</pe:sheetcolumn>
</c:forEach>
<f:facet name="footer">
<h:outputText value="#{sheetDynamicController.filteredSheetRows.size()} Records"/>
</f:facet>
</pe:sheet>
</h:form>
<script type="text/javascript">
function sheetExtender() {
// this = widget
// this.cfg = JSON configuration
this.cfg.trimWhitespace = true;
};
$(document).ready(function () {
var $hot = PF('sheetDynamicWidget').ht;
$hot.updateSettings({
contextMenu: {
callback: function (key, options) {
if (key === 'about') {
setTimeout(function () {
// timeout is used to make sure the menu collapsed before alert is shown
alert("PrimeFaces Extensions Rocks! This is a context menu with default and custom options mixed");
}, 100);
}
},
items: {
"row_above": {
disabled: function () {
// if first row, disable this option
return $hot.getSelected()[0] === 0;
}
},
"row_below": {},
"hsep1": "---------",
"remove_row": {
name: 'Remove this row, ok?',
disabled: function () {
// if first row, disable this option
return $hot.getSelected()[0] === 0
}
},
"hsep2": "---------",
"about": {name: 'About...'}
}
}
});
});
</script>
</div>
package org.primefaces.extensions.showcase.controller.sheet;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.primefaces.extensions.component.sheet.Sheet;
import org.primefaces.extensions.event.SheetEvent;
import org.primefaces.extensions.model.sheet.SheetUpdate;
import org.primefaces.extensions.showcase.model.sheet.Asset;
import org.primefaces.extensions.showcase.model.sheet.AssetType;
import org.primefaces.extensions.showcase.model.sheet.PlatformArchType;
import org.primefaces.extensions.showcase.model.sheet.PlatformType;
/**
* {@link Sheet} Controller.
*
* @author Melloware [email protected]
*/
@Named
@ViewScoped
public class SheetController implements Serializable {
@Serial
private static final long serialVersionUID = 20120224L;
private List<Asset> assets = new ArrayList<>();
private List<Asset> filteredAssets = new ArrayList<>();
public SheetController() {
addAssets(40, PlatformType.Linux, PlatformArchType.AMD64, AssetType.SERVER);
addAssets(50, PlatformType.Windows, PlatformArchType.I386, AssetType.DESKTOP);
addAssets(60, PlatformType.Mac, PlatformArchType.OTHER, AssetType.LAPTOP);
addAssets(5, null, null, AssetType.PRINTER);
}
public void cellChangeEvent(final SheetEvent event) {
final Sheet sheet = event.getSheet();
final List<SheetUpdate> updates = sheet.getUpdates();
// A SheetUpdate exists for each column updated, the same row may
// appear more than once. For this reason we will track those we already
// persisted
final HashSet<Asset> processed = new HashSet<Asset>();
int rowUpdates = 0;
for (final SheetUpdate update : updates) {
final Asset asset = (Asset) update.getRowData();
if (processed.contains(asset)) {
continue;
}
System.out.println("Asset " + asset.getAssetId() + " updated.");
rowUpdates++;
}
sheet.commitUpdates();
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("Update Success", rowUpdates + " rows updated"));
}
private void addAssets(final int count, final PlatformType platform, final PlatformArchType arch,
final AssetType type) {
for (int i = 0; i < count; i++) {
final Asset asset = new Asset();
asset.setAssetId(RandomUtils.secure().randomLong());
asset.setActive(RandomUtils.secure().randomBoolean());
asset.setPlatform(platform);
asset.setPlatformArch(arch);
asset.setHostName(type.toString().toLowerCase() + i + ".example.lan");
asset.setAssetType(type);
asset.setIcon("<i class='fas fa-info-circle' style='color:cornflowerblue' />");
asset.setPurchaseDate(new Date());
asset.setPurchaseTime(new Date());
asset.setValue1(RandomUtils.secure().randomInt(1, 1000));
asset.setPassword(RandomStringUtils.secure().nextAlphabetic(6));
asset.setPurchasePrice(
BigDecimal.valueOf(RandomUtils.secure().randomDouble(1.11, 999.99) * (RandomUtils.secure().randomBoolean() ? -1 : 1))
.setScale(2, RoundingMode.HALF_UP));
getAssets().add(asset);
}
}
public List<Asset> getAssets() {
return assets;
}
public void setAssets(final List<Asset> assets) {
this.assets = assets;
}
public List<Asset> getFilteredAssets() {
return filteredAssets;
}
public void setFilteredAssets(final List<Asset> filteredAssets) {
this.filteredAssets = filteredAssets;
}
}
package org.primefaces.extensions.showcase.model.sheet;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
public class Asset implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long assetId;
private Date purchaseDate;
private Date purchaseTime;
private String hostName;
private String description;
private String icon;
private BigDecimal purchasePrice;
private PlatformType platform;
private PlatformArchType platformArch;
private AssetType assetType;
private Boolean active;
private String comment;
private String password;
private Date lastUpdated;
private String patchLevel;
private String allocatedTo;
private String location;
private Integer value1;
private Integer value2;
private Integer value3;
private Integer value4;
private Integer value5;
private Integer value6;
private Integer value7;
private Integer value8;
private Integer value9;
private Integer value10;
public Long getAssetId() {
return assetId;
}
public void setAssetId(final Long assetId) {
this.assetId = assetId;
}
public Date getPurchaseDate() {
return purchaseDate;
}
public void setPurchaseDate(final Date purchaseDate) {
this.purchaseDate = purchaseDate;
}
public String getHostName() {
return hostName;
}
public void setHostName(final String hostName) {
this.hostName = hostName;
}
public String getDescription() {
return description;
}
public void setDescription(final String description) {
this.description = description;
}
public String getIcon() {
return icon;
}
public void setIcon(final String icon) {
this.icon = icon;
}
public BigDecimal getPurchasePrice() {
return purchasePrice;
}
public void setPurchasePrice(final BigDecimal purchasePrice) {
this.purchasePrice = purchasePrice;
}
public PlatformType getPlatform() {
return platform;
}
public void setPlatform(final PlatformType platform) {
this.platform = platform;
}
public PlatformArchType getPlatformArch() {
return platformArch;
}
public void setPlatformArch(final PlatformArchType platformArch) {
this.platformArch = platformArch;
}
public AssetType getAssetType() {
return assetType;
}
public void setAssetType(final AssetType assetType) {
this.assetType = assetType;
}
public String getComment() {
return comment;
}
public void setComment(final String comment) {
this.comment = comment;
}
public Date getLastUpdated() {
return lastUpdated;
}
public void setLastUpdated(final Date lastUpdated) {
this.lastUpdated = lastUpdated;
}
public String getPatchLevel() {
return patchLevel;
}
public void setPatchLevel(final String patchLevel) {
this.patchLevel = patchLevel;
}
public String getAllocatedTo() {
return allocatedTo;
}
public void setAllocatedTo(final String allocatedTo) {
this.allocatedTo = allocatedTo;
}
public String getLocation() {
return location;
}
public void setLocation(final String location) {
this.location = location;
}
public Integer getValue1() {
return value1;
}
public void setValue1(final Integer value1) {
this.value1 = value1;
}
public Integer getValue2() {
return value2;
}
public void setValue2(final Integer value2) {
this.value2 = value2;
}
public Integer getValue3() {
return value3;
}
public void setValue3(final Integer value3) {
this.value3 = value3;
}
public Integer getValue4() {
return value4;
}
public void setValue4(final Integer value4) {
this.value4 = value4;
}
public Integer getValue5() {
return value5;
}
public void setValue5(final Integer value5) {
this.value5 = value5;
}
public Integer getValue6() {
return value6;
}
public void setValue6(final Integer value6) {
this.value6 = value6;
}
public Integer getValue7() {
return value7;
}
public void setValue7(final Integer value7) {
this.value7 = value7;
}
public Integer getValue8() {
return value8;
}
public void setValue8(final Integer value8) {
this.value8 = value8;
}
public Integer getValue9() {
return value9;
}
public void setValue9(final Integer value9) {
this.value9 = value9;
}
public Integer getValue10() {
return value10;
}
public void setValue10(final Integer value10) {
this.value10 = value10;
}
public String getPassword() {
return password;
}
public void setPassword(final String password) {
this.password = password;
}
public Boolean getActive() {
return active;
}
public void setActive(final Boolean active) {
this.active = active;
}
public Date getPurchaseTime() {
return purchaseTime;
}
public void setPurchaseTime(final Date purchaseTime) {
this.purchaseTime = purchaseTime;
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (assetId == null ? 0 : assetId.hashCode());
result = prime * result + (hostName == null ? 0 : hostName.hashCode());
return result;
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Asset other = (Asset) obj;
if (assetId == null) {
if (other.assetId != null) {
return false;
}
}
else if (!assetId.equals(other.assetId)) {
return false;
}
if (hostName == null) {
return other.hostName == null;
}
else {
return hostName.equals(other.hostName);
}
}
public Integer getTotal() {
return (value1 == null ? 0 : value1) +
(value2 == null ? 0 : value2) +
(value3 == null ? 0 : value3) +
(value4 == null ? 0 : value4) +
(value5 == null ? 0 : value5) +
(value6 == null ? 0 : value6) +
(value7 == null ? 0 : value7) +
(value8 == null ? 0 : value8) +
(value9 == null ? 0 : value9) +
(value10 == null ? 0 : value10);
}
}
package org.primefaces.extensions.showcase.model.sheet;
public enum PlatformType {
Windows, Linux, Mac
}
package org.primefaces.extensions.showcase.model.sheet;
public enum PlatformArchType {
I386, AMD64, OTHER
}
package org.primefaces.extensions.showcase.model.sheet;
public enum AssetType {
DESKTOP, SERVER, LAPTOP, PRINTER, OTHER
}
package org.primefaces.extensions.showcase.controller.sheet;
import java.util.*;
import jakarta.annotation.*;
import jakarta.enterprise.context.*;
import jakarta.faces.model.*;
import jakarta.inject.*;
import org.primefaces.extensions.showcase.model.sheet.*;
@Named
@ApplicationScoped
public class SheetOptionProducer {
private List<SelectItem> assetTypes;
private List<SelectItem> platformTypes;
private List<SelectItem> archTypes;
@PostConstruct
private void init() {
assetTypes = createEnumList(AssetType.values());
platformTypes = createEnumList(PlatformType.values());
archTypes = createEnumList(PlatformArchType.values());
}
private static <T extends Enum<?>> List<SelectItem> createEnumList(final T[] values) {
final List<SelectItem> result = new ArrayList<>();
result.add(new SelectItem("", "All"));
for (final T value : values) {
result.add(new SelectItem(value, value.name()));
}
return result;
}
public List<SelectItem> getAssetTypes() {
return assetTypes;
}
public List<SelectItem> getPlatformTypes() {
return platformTypes;
}
public List<SelectItem> getArchTypes() {
return archTypes;
}
}
package org.primefaces.extensions.showcase.controller.sheet;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
import org.apache.commons.lang3.RandomUtils;
import org.primefaces.extensions.showcase.model.sheet.Asset;
import org.primefaces.extensions.showcase.model.sheet.AssetType;
import org.primefaces.extensions.showcase.model.sheet.PlatformType;
@Named
@ViewScoped
public class SheetExportController implements Serializable {
@Serial
private static final long serialVersionUID = 20240224L;
private List<Asset> assets = new ArrayList<>();
private List<Asset> filteredAssets = new ArrayList<>();
public SheetExportController() {
addAssets(40, PlatformType.Linux, AssetType.SERVER);
addAssets(50, PlatformType.Windows, AssetType.DESKTOP);
addAssets(60, PlatformType.Mac, AssetType.LAPTOP);
addAssets(5, null, AssetType.PRINTER);
}
private void addAssets(final int count, final PlatformType platform, final AssetType type) {
for (int i = 0; i < count; i++) {
final Asset asset = new Asset();
asset.setAssetId(RandomUtils.secure().randomLong());
asset.setActive(RandomUtils.secure().randomBoolean());
asset.setPlatform(platform);
asset.setAssetType(type);
asset.setPurchaseDate(new Date());
asset.setPurchasePrice(
BigDecimal.valueOf(RandomUtils.secure().randomDouble(1.11, 999.99) * (RandomUtils.secure().randomBoolean() ? -1 : 1))
.setScale(2, RoundingMode.HALF_UP));
getAssets().add(asset);
}
}
public List<Asset> getAssets() {
return assets;
}
public void setAssets(final List<Asset> assets) {
this.assets = assets;
}
public List<Asset> getFilteredAssets() {
return filteredAssets;
}
public void setFilteredAssets(final List<Asset> filteredAssets) {
this.filteredAssets = filteredAssets;
}
}
package org.primefaces.extensions.showcase.controller.sheet;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
import org.apache.commons.lang3.RandomUtils;
import org.primefaces.extensions.component.sheet.Sheet;
import org.primefaces.extensions.showcase.model.sheet.DynaSheetCell;
import org.primefaces.extensions.showcase.model.sheet.DynaSheetRow;
/**
* {@link Sheet} Controller.
*
* @author Melloware [email protected]
*/
@Named
@ViewScoped
public class SheetDynamicController implements Serializable {
@Serial
private static final long serialVersionUID = 20120224L;
private List<DynaSheetRow> sheetRows = new ArrayList<>();
private List<DynaSheetRow> filteredSheetRows = new ArrayList<>();
private List<Integer> hoursOfDay = new ArrayList<>();
public SheetDynamicController() {
addRows(24);
}
private void addRows(final int count) {
for (int i = 0; i < count; i++) {
final DynaSheetRow row = new DynaSheetRow();
row.setId(RandomUtils.secure().randomLong());
row.setReadOnly(false);
final Integer hourOfDay = Integer.valueOf(i);
hoursOfDay.add(hourOfDay);
for (int j = 0; j < count; j++) {
row.getCells().add(DynaSheetCell.create(Integer.valueOf(j), RandomUtils.secure().randomInt(1, 1000)));
}
getSheetRows().add(row);
}
}
public List<DynaSheetRow> getSheetRows() {
return sheetRows;
}
public void setSheetRows(final List<DynaSheetRow> sheetRows) {
this.sheetRows = sheetRows;
}
public List<Integer> getHoursOfDay() {
return hoursOfDay;
}
public void setHoursOfDay(final List<Integer> hoursOfDay) {
this.hoursOfDay = hoursOfDay;
}
public List<DynaSheetRow> getFilteredSheetRows() {
return filteredSheetRows;
}
public void setFilteredSheetRows(final List<DynaSheetRow> filteredSheetRows) {
this.filteredSheetRows = filteredSheetRows;
}
}
package org.primefaces.extensions.showcase.model.sheet;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* Model object to represent a row in sheet component.
*/
public class DynaSheetRow implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long id;
private List<DynaSheetCell> cells = new ArrayList<>();
private boolean readOnly;
/**
* Gets the {@link #id}.
*
* @return Returns the {@link #id}.
*/
public Long getId() {
return id;
}
/**
* Sets the {@link #id}.
*
* @param id The {@link #id} to set.
*/
public void setId(final Long id) {
this.id = id;
}
/**
* Gets the {@link #cells}.
*
* @return Returns the {@link #cells}.
*/
public List<DynaSheetCell> getCells() {
return cells;
}
/**
* Sets the {@link #cells}.
*
* @param cells The {@link #cells} to set.
*/
public void setCells(final List<DynaSheetCell> cells) {
this.cells = cells;
}
/**
* Gets the {@link #readOnly}.
*
* @return Returns the {@link #readOnly}.
*/
public boolean isReadOnly() {
return readOnly;
}
/**
* Sets the {@link #readOnly}.
*
* @param readOnly The {@link #readOnly} to set.
*/
public void setReadOnly(final boolean readOnly) {
this.readOnly = readOnly;
}
}
package org.primefaces.extensions.showcase.model.sheet;
import java.io.Serial;
import java.io.Serializable;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.CompareToBuilder;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
/**
* Model object to represent a single cell in sheet component
*/
public class DynaSheetCell implements Comparable<DynaSheetCell>, Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Integer value;
private String style;
private Integer hourOfDay;
public static DynaSheetCell create(final Integer hourOfDay, final Integer value) {
final DynaSheetCell cell = new DynaSheetCell();
cell.setHourOfDay(hourOfDay);
cell.setValue(value);
cell.setStyle(StringUtils.EMPTY);
if (hourOfDay == 2) {
cell.setStyle("cell-blue");
}
if (hourOfDay == 3) {
cell.setStyle("cell-orange");
}
return cell;
}
/**
* Gets the {@link #hourOfDay}.
*
* @return Returns the {@link #hourOfDay}.
*/
public Integer getHourOfDay() {
return hourOfDay;
}
/**
* Sets the {@link #hourOfDay}.
*
* @param hourOfDay The {@link #hourOfDay} to set.
*/
public void setHourOfDay(final Integer hourOfDay) {
this.hourOfDay = hourOfDay;
}
/**
* Gets the {@link #value}.
*
* @return Returns the {@link #value}.
*/
public Integer getValue() {
return value;
}
/**
* Sets the {@link #value}.
*
* @param value The {@link #value} to set.
*/
public void setValue(final Integer value) {
this.value = value;
}
/**
* Gets the {@link #style}.
*
* @return Returns the {@link #style}.
*/
public String getStyle() {
return style;
}
/**
* Sets the {@link #style}.
*
* @param style The {@link #style} to set.
*/
public void setStyle(final String style) {
this.style = style;
}
/**
* {@inheritDoc}
*/
@Override
public int compareTo(final DynaSheetCell other) {
return new CompareToBuilder().append(value, other.value).toComparison();
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(final Object other) {
if (!(other instanceof DynaSheetCell)) {
return false;
}
final DynaSheetCell castOther = (DynaSheetCell) other;
return new EqualsBuilder().append(getValue(), castOther.getValue())
.append(getHourOfDay(), castOther.getHourOfDay()).isEquals();
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return new HashCodeBuilder().append(getValue()).append(getHourOfDay())
.toHashCode();
}
}