Table Slicer Data

Besides GeneralSlicerData, SpreadJS also provides TableSlicerData. The data source of TableSlicerData is a SpreadJS SheetTable. You must set a SheetTable to TableSlicerData's constructor if you want to use it.

The information for rowFilter and the checked state on the filter dialog of SheetTable are synchronized with the filter result of Slicers attached with TableSlicerData. All of the slicers (attached with TableSlicerData) receive the onFilter notice and get the filtered result after the SheetTable filters completely with code or the filter dialog. You can use TableSlicerData as follows:
import * as React from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; import { AppFunc } from './app-func'; // import { App } from './app-class'; // 1. Functional Component sample createRoot(document.getElementById('app')).render(<AppFunc />); // 2. Class Component sample // createRoot(document.getElementById('app')).render(<App />);
import * as React from 'react'; import { SpreadSheets } from '@mescius/spread-sheets-react'; import "@mescius/spread-sheets-shapes"; import "@mescius/spread-sheets-slicers"; export function AppFunc() { const initSpread = (spread) => { let sheet = spread.getActiveSheet(); // Define data source. let columnNames = ["Name", "Sex", "City", "Birthday"], data = [ ["Bob", "Man", "NewYork", "1968/06/08"], ["Betty", "Woman", "Washington", "1972/07/03"], ["Alice", "Woman", "Atlanta", "1964/03/02"], ["Tom", "Man", "Houston", "1986/12/03"], ["Jenny", "Woman", "Washington", "1956/10/13"], ["Nacy", "Woman", "NewYork", "1989/01/14"], ["John", "Man", "Houston", "1995/01/01"], ["Mark", "Man", "Atlanta", "1965/11/11"], ["Susan", "Woman", "Atlanta", "1983/07/08"] ]; // Create a table. let table = sheet.tables.addFromDataSource("table1", 1, 1, data); table.setColumnName(0, columnNames[0]); table.setColumnName(1, columnNames[1]); table.setColumnName(2, columnNames[2]); table.setColumnName(3, columnNames[3]); sheet.getRange(-1, 1, -1, 6).width(80); // Get TableSlicerData from table. let slicerData = table.getSlicerData(); // Create a custom slicer and add it to dom tree. let slicer1 = new CustomSlicer(document.getElementById("cityContainer"), 'City'); slicer1.setData(slicerData, "City"); let slicer2 = new CustomSlicer(document.getElementById("sexContainer"), 'Sex'); slicer2.setData(slicerData, "Sex"); } return (<div class="sample-tutorial"> <div class="sample-spreadsheets"> <SpreadSheets workbookInitialized={spread => initSpread(spread)}> </SpreadSheets> </div> <div class="options-container"> <div id="cityContainer" class="sample-group"></div> <div id="sexContainer" class="sample-group"></div> </div> </div>); } class CustomSlicer { constructor(container, name) { this.container = container; this.name = name; this.slicerData = null; this.columnName = null; } setData(slicerData, columnName) { this.slicerData = slicerData; this.columnName = columnName; this.slicerData.attachListener(this); this.onDataLoaded(); } onDataLoaded() { let columnName = this.columnName, exclusiveData = this.slicerData.getExclusiveData(columnName); // Create slicer dom tree. let strong = document.createElement('strong'); strong.innerText = this.name + ':'; let br = document.createElement('br'); this.container.appendChild(strong); this.container.appendChild(br); let domString = "", id; let div = document.createElement('div'); div.setAttribute('class', 'option-group') for (let i = 0; i < exclusiveData.length; i++) { id = columnName + (i + 1); domString += '<input type="checkbox" name="' + columnName + '" value="' + exclusiveData[i] + '" id="' + id + '" checked>'; domString += '<label for="' + id + '">' + exclusiveData[i] + '</label></br>'; } div.innerHTML = domString; this.container.appendChild(div); // Attach events to dom element. let self = this; document.querySelector('.options-container').addEventListener('change', function (e) { // Invoke getExclusiveData method to get exclusive data from slicerData. let exclusiveData = self.slicerData.getExclusiveData(self.columnName); // parent = this.parentNode.parentNode; let items = document.querySelectorAll('.options-container input'); let indexes = []; for (let i = 0, length = items.length; i < length; i++) { if (items[i].checked) { let value = items[i].value; if (!isNaN(parseInt(value))) { value = parseInt(value); } if (exclusiveData.indexOf(value) != -1) { indexes.push(exclusiveData.indexOf(value)) } } } if (indexes.length === 0) { // Invoke doUnfilter method when all item are not selected. self.slicerData.doUnfilter(self.columnName); } else { // Invoke doFilter method when any item is selected. self.slicerData.doFilter(self.columnName, { exclusiveRowIndexes: indexes }); } }); } }
import * as React from 'react'; import { SpreadSheets } from '@mescius/spread-sheets-react'; import "@mescius/spread-sheets-shapes"; import "@mescius/spread-sheets-slicers"; const Component = React.Component; export class App extends Component { constructor(props) { super(props); } render() { return (<div class="sample-tutorial"> <div class="sample-spreadsheets"> <SpreadSheets workbookInitialized={spread => this.initSpread(spread)}> </SpreadSheets> </div> <div class="options-container"> <div id="cityContainer" class="sample-group"></div> <div id="sexContainer" class="sample-group"></div> </div> </div>); } initSpread(spread) { let sheet = spread.getActiveSheet(); // Define data source. let columnNames = ["Name", "Sex", "City", "Birthday"], data = [ ["Bob", "Man", "NewYork", "1968/06/08"], ["Betty", "Woman", "Washington", "1972/07/03"], ["Alice", "Woman", "Atlanta", "1964/03/02"], ["Tom", "Man", "Houston", "1986/12/03"], ["Jenny", "Woman", "Washington", "1956/10/13"], ["Nacy", "Woman", "NewYork", "1989/01/14"], ["John", "Man", "Houston", "1995/01/01"], ["Mark", "Man", "Atlanta", "1965/11/11"], ["Susan", "Woman", "Atlanta", "1983/07/08"] ]; // Create a table. let table = sheet.tables.addFromDataSource("table1", 1, 1, data); table.setColumnName(0, columnNames[0]); table.setColumnName(1, columnNames[1]); table.setColumnName(2, columnNames[2]); table.setColumnName(3, columnNames[3]); sheet.getRange(-1, 1, -1, 6).width(80); // Get TableSlicerData from table. let slicerData = table.getSlicerData(); // Create a custom slicer and add it to dom tree. let slicer1 = new CustomSlicer(document.getElementById("cityContainer"), 'City'); slicer1.setData(slicerData, "City"); let slicer2 = new CustomSlicer(document.getElementById("sexContainer"), 'Sex'); slicer2.setData(slicerData, "Sex"); } } class CustomSlicer { constructor(container, name) { this.container = container; this.name = name; this.slicerData = null; this.columnName = null; } setData(slicerData, columnName) { this.slicerData = slicerData; this.columnName = columnName; this.slicerData.attachListener(this); this.onDataLoaded(); } onDataLoaded() { let columnName = this.columnName, exclusiveData = this.slicerData.getExclusiveData(columnName); // Create slicer dom tree. let strong = document.createElement('strong'); strong.innerText = this.name + ':'; let br = document.createElement('br'); this.container.appendChild(strong); this.container.appendChild(br); let domString = "", id; let div = document.createElement('div'); div.setAttribute('class', 'option-group') for (let i = 0; i < exclusiveData.length; i++) { id = columnName + (i + 1); domString += '<input type="checkbox" name="' + columnName + '" value="' + exclusiveData[i] + '" id="' + id + '" checked>'; domString += '<label for="' + id + '">' + exclusiveData[i] + '</label></br>'; } div.innerHTML = domString; this.container.appendChild(div); // Attach events to dom element. let self = this; document.querySelector('.options-container').addEventListener('change', function (e) { // Invoke getExclusiveData method to get exclusive data from slicerData. let exclusiveData = self.slicerData.getExclusiveData(self.columnName); // parent = this.parentNode.parentNode; let items = document.querySelectorAll('.options-container input'); let indexes = []; for (let i = 0, length = items.length; i < length; i++) { if (items[i].checked) { let value = items[i].value; if (!isNaN(parseInt(value))) { value = parseInt(value); } if (exclusiveData.indexOf(value) != -1) { indexes.push(exclusiveData.indexOf(value)) } } } if (indexes.length === 0) { // Invoke doUnfilter method when all item are not selected. self.slicerData.doUnfilter(self.columnName); } else { // Invoke doFilter method when any item is selected. self.slicerData.doFilter(self.columnName, { exclusiveRowIndexes: indexes }); } }); } }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/react/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <!-- SystemJS --> <script src="$DEMOROOT$/en/react/node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('$DEMOROOT$/en/lib/react/license.js').then(function () { System.import('./src/app'); }); </script> </head> <body> <div id="app" style="height: 100%;"></div> </body> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-spreadsheets { width: calc(100% - 280px); height: 100%; overflow: auto; float: left; } .options-container { float: right; width: 280px; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; overflow: auto; } label { display: inline-block; margin: 6px 0; } strong { display: inline-block; margin: 12px 0; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true, react: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-shapes': 'npm:@mescius/spread-sheets-shapes/index.js', '@mescius/spread-sheets-slicers': 'npm:@mescius/spread-sheets-slicers/index.js', '@mescius/spread-sheets-react': 'npm:@mescius/spread-sheets-react/index.js', '@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js', 'react': 'npm:react/cjs/react.production.js', 'react-dom': 'npm:react-dom/cjs/react-dom.production.js', 'react-dom/client': 'npm:react-dom/cjs/react-dom-client.production.js', 'scheduler': 'npm:scheduler/cjs/scheduler.production.js', 'css': 'npm:systemjs-plugin-css/css.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', 'systemjs-babel-build':'npm:systemjs-plugin-babel/systemjs-babel-browser.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'jsx' }, "node_modules": { defaultExtension: 'js' }, } }); })(this);