The slicer works with GeneralSlicerData based on the following steps:
Create a new GeneralSlicerData instance with your data.
Create a new custom slicer and attach it to GeneralSlicerData.
Get the column data from GeneralSlicerData and build the slicer UI.
Respond to the UI events and invoke the GeneralSlicerData doFilter method.
Get the filtered result from GeneralSlicerData and update the slicer UI.
The following API will help you write simpler code:
getData: Get all data for the specified column.
getExclusiveData: Get exclusive data (non-repeating data) for the specified column.
doFilter: Filter the data that corresponds to the specified column and exclusive data indexes.
doUnfilter: Un-filter the data that corresponds to the specified column.
attachListener: Attach slicer to slicer data.
detachListener: Detach slicer from slicer data.
onFiltered: Occurs after the slicer data has been filtered.
<template>
<div class="sample-tutorial">
<div id="ss" class="sample-spreadsheets"></div>
<div class="options-container">
<div id="info">Use GeneralSlicerData on the left table to filter data by City and Sex columns.</div>
<p>
<div id="info">Filter data by the third column using the slicer below:</div>
</p>
<div id="cityContainer"></div>
<p>
<div id="info">Filter data by the second column using the slicer below:</div>
</p>
<div id="sexContainer"></div>
</div>
</div>
</template>
<script>
import GC from "@mescius/spread-sheets";
import { onMounted } from 'vue';
import "@mescius/spread-sheets-vue";
export default {
name: 'App',
setup() {
// Define data.
const columnNames = ["Name", "Sex", "City", "Birthday"];
const 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"]
];
// Define methods.
const initFilteredResultList = () => {
let tableStr = '';
for (let i = 0; i < columnNames.length; i++) {
tableStr += "<th>" + columnNames[i] + "</th>";
}
for (let i = 0; i < data.length; i++) {
tableStr += "<tr>";
for (let j = 0; j < data[i].length; j++) {
tableStr += "<td>" + data[i][j] + "</td>";
}
tableStr += "</tr>";
}
let table = document.createElement('table');
table.border = '1';
table.cellPadding = '0';
table.cellSpacing = '0';
table.innerHTML = tableStr;
document.getElementById('ss').appendChild(table);
};
const setData = (slicer, slicerData, columnName) => {
slicer.setData(slicerData, columnName);
};
// Define mounted hook.
onMounted(() => {
// Build data UI.
initFilteredResultList(columnNames, data);
// Create GeneralSlicerData.
const slicerData = new GC.Spread.Slicers.GeneralSlicerData(data, columnNames);
// Create a custom slicer and attach it to dom tree.
const slicer1 = new CustomSlicer(document.getElementById('cityContainer'));
setData(slicer1, slicerData, 'City');
const slicer2 = new CustomSlicer(document.getElementById('sexContainer'));
setData(slicer2, slicerData, 'Sex');
});
return {
columnNames,
data
};
}
};
class CustomSlicer {
constructor(container) {
this.container = container;
this.slicerData = null;
this.columnName = null;
}
setData(slicerData, columnName) {
this.slicerData = slicerData;
this.columnName = columnName;
// Invoke attachListener method.
this.slicerData.attachListener(this);
this.onDataLoaded();
}
onDataLoaded() {
let columnName = this.columnName,
exclusiveData = this.slicerData.getExclusiveData(columnName);
let domString = '<span>' + this.columnName + ':</span>' + '<br />';
exclusiveData.forEach(function (exclusiveDataItem, index) {
let id = columnName + index + 1;
domString += '<input type="checkbox" class="' + columnName + '" value="' + exclusiveDataItem + '" id="' + id + '" style="margin-left:10px;" checked>' +
'<label for="' + id + '">' + exclusiveDataItem + '</label>' +
'<br />';
});
this.container.innerHTML = domString;
let self = this;
let elements = document.getElementsByClassName(columnName);
for (let _index = 0; _index < elements.length; _index++) {
let element = elements[_index]
element.onchange = function (e) {
let parent = e.target.parentNode,
items = parent.childNodes,
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);
}
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
});
}
}
}
}
onFiltered() {
let slicerdata = this.slicerData;
let filteredRowIndexs = slicerdata.getFilteredRowIndexes();
let trs = document.getElementsByTagName('tr');
for (let i = 0; i < slicerdata.data.length; i++) {
if (filteredRowIndexs.indexOf(i) !== -1) {
trs[i + 1].style.display = '';
} else {
trs[i + 1].style.display = 'none';
}
}
}
}
</script>
<style scoped>
#app {
height: 100%;
}
.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;
min-width: 90px;
margin: 6px 0;
}
hr {
border-color: #fff;
opacity: .2;
margin: 12px 0;
}
table th,
table td {
padding: 4px 8px;
}
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
</style>
<!DOCTYPE html>
<html lang="en" style="height:100%;font-size:14px;">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>SpreadJS VUE</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css"
href="$DEMOROOT$/en/vue3/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<script src="$DEMOROOT$/en/vue3/node_modules/systemjs/dist/system.src.js"></script>
<script src="./systemjs.config.js"></script>
<script src="./compiler.js" type="module"></script>
<script>
var System = SystemJS;
System.import("./src/app.js");
System.import('$DEMOROOT$/en/lib/vue3/license.js');
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
(function (global) {
SystemJS.config({
transpiler: 'plugin-babel',
babelOptions: {
es2015: true
},
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
packageConfigPaths: [
'./node_modules/*/package.json',
"./node_modules/@mescius/*/package.json",
"./node_modules/@babel/*/package.json",
"./node_modules/@vue/*/package.json"
],
map: {
'vue': "npm:vue/dist/vue.esm-browser.js",
'tiny-emitter': 'npm:tiny-emitter/index.js',
'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js',
"systemjs-babel-build": "npm:systemjs-plugin-babel/systemjs-babel-browser.js",
'@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js',
'@mescius/spread-sheets-resources-en': 'npm:@mescius/spread-sheets-resources-en/index.js',
'@mescius/spread-sheets-vue': 'npm:@mescius/spread-sheets-vue/index.js',
},
meta: {
'*.css': { loader: 'systemjs-plugin-css' },
'*.vue': { loader: "../plugin-vue/index.js" }
}
});
})(this);