Skip to main content

Table Overview

A table runs its pipeline and returns two things: fields and rows.

A table pipeline is explained elsewhere (provide link).

.fields​

fields is an array of Field elements. A Field is an object that describes a value found in a row. At minimum it will have a name and a type. It may also have a label, valueLabels, or even arbitrary data, all of which is passed along to a renderer.

// fields:
[
{ "name": "uuid", "type": "string" },
{ "name": "S1", "label": "Gender", "type": "number" },
{ "name": "Q1", "label": "Customer Satisfaction", "type": "number" },
...
]

.rows​

Rows is an array of Row elements. A Row element is an object with a property for each field. The name of the property matches the name of the field. A value could be a string, a number, or any valid JSON token (e.g., an object, boolean or null).

// rows:
[
{ "uuid": "AAB-FXGXY-BTX", "S1": 1, "Q1": 2 },
{ "uuid": "AAB-XBJMT-HUA", "S1": 1, "Q1": 3 },
{ "uuid": "AAE-FYPXK-QPY", "S1": 2, "Q1": 1 },
{ "uuid": "AAF-GFBBR-NGH", "S1": 1, "Q1": 5 },
{ "uuid": "AAG-FRRSQ-CM3", "S1": 2, "Q1": 4 },
]

.dataPlugins​

Plugins can modify the rows and fields returned.

const hackDataPlugin = (args) => {
const { fields, rows } = args;
// add a row
const newRows = [
...(rows || []),
{ label: "Sample Size", "x1": 100 }
];
return {
...args,
rows: newRows
}
}

.tableSettings​

There are probably some settings that the table will ask for somewhere in the UI.

.renderTableplugins​

Plugins can modify the renderTable output.

.renderTable​

The fields, rows and tableSettings described above are passed into a render function.

It looks something like this, but a bit more complex since renderCell can return multiple cells if it wants to.

const renderTable = (args) => {

const { fields, rows, tableSettings, plugins } = args;

// returns some stuff
let renderedRows = [];
if(rows && fields){
for(let row of rows){
let renderedRow = []; // should I refactor out a renderRow function with renderRow plugins? it would potentially return multiple rows
for(let field of fields){
const c = renderCell({ ...args, field, row }); // in real life could potentially return multiple cells (not handled here)
renderedRow.push(c);
}
renderedRows.push(renderedRow);
}
}

// apply plugins if any
if( plugins ){
for(let plugin of plugins ){
renderedRows = plugin({ ...args, renderedRows });
}
}

return renderedRows;
}

.renderCellPlugins​

Plugins can modify the renderCell output. A plugin is called for every cell, so it's the plugin's responsibility to decide (by looking at fieldObj or something) whether or not to modify the cell.

.renderCell​

// returns a cell object (JSON). See renderPCell or renderXCell docs.
const renderCell = (args) => {

let renderedCell;

// ...
const { row, field } = args;

// something like this:
renderedCell = {
...field, // add everything the field has
};

// loop through all the prior fields that have a prop like .rowHeader meaning they come from row dims (not col dims)
// add those props
// todo:
{

}

// add the value?
renderedCell.value = row[field.name];

if( field.type === "string" ){
renderedCell.formatCategory = "General";
}
else if( field.type === "number" ){
renderedCell.formatCategory = "Custom";
renderedCell.customFormat = field.valueFormat || row.valueFormat || "0.2f"; // where does row valueFormat come from? (do i need to look for it)?
}
else if( field.type === "object" ){
// todo (show label or value)??
renderedCell.value = row[field.name]?.label; // ??
}
else{
// boolean, date, unknown
}

// apply plugins if any
if( plugins ){
for(let plugin of plugins){
renderedCell = plugin({ ...args, renderedCell });
}
}

return renderedCell;

}

customLowNCellPlugin​

const customLowNCellPlugin = (args, pluginArgs) => {

const newCell = { ...args.renderedCell };

const lowN = pluginArgs.lowN || args.props.lowN;
if( newCell.value < lowN ){
// todo: mask the value somehow
newCell.value = "**";
newCell.backgroundColor = "red";
}

return newCell;

}

showFreqCellPlugin​

const showFreqCellPlugin = (args) => {

const originalCell = args.renderedCell;

const { row, field } = args;
let newFreqCell = {
// something like this:
value: row[field.name]?.freq;
formatCategory = "Custom";
customFormat = ",.0f";
}

// actually i don't like this returning of arrays. i think instead i'll do e.., .cellsBelow = [newFreqCell]
// this returns the new cell below the original
return [originalCell, newFreqCell];

// actually i don't like this returning of arrays. i think instead i'll do e.., .cellsNextTo = [newFreqCell]
// this would return the new cell to the right of the original
return [[originalCell, newFreqCell]];

}

showStandardTestResultsPlugin​

const showStandardTestResultsPlugin = (args) => {

const originalCell = args.renderedCell;

const { row, field } = args;
let newCell = {
// something like this:
value: row[field.name]?.testResults;
// todo
}

// this returns the new cell below the original
return {
...originalCell,
belowCell: newCell // something like this?
}


}