Sorting table component

Let’s start by defining our storage, initial state and our handlers

Example

// Define the initial state
const iniState = {
	sortBy: 'name',
	dir: 1,
	tableData: [
	{
		name: 'Jhon Doe',
		Score: Math.floor(Math.random() * (500 - 100) + 100),
		'Hours played': Math.floor(Math.random() * (100 - 10) + 10)
	},
	{
		name: 'Aaron Smith',
		Score: Math.floor(Math.random() * (500 - 100) + 100),
		'Hours played': Math.floor(Math.random() * (100 - 10) + 10)
	},
	{
		name: 'Jessica Sort',
		Score: Math.floor(Math.random() * (500 - 100) + 100),
		'Hours played': Math.floor(Math.random() * (100 - 10) + 10)
	}
	]
};
// handle the events, in out case the change sort
const handlers = {
	'CHANGE_SORT': (action, state) => {
		// if is the same column revert the sorting
		if (action.sortBy === state.sortBy) {
			state.dir *= -1; 
		} else {
			state.dir = 1;
			state.sortBy = action.sortBy;
		}
		// sort table by column
		state.tableData.sort((a, b) => {
			if(a[state.sortBy] > b[state.sortBy]) {
				return -1 * state.dir
			} else {
				return state.dir
			}
			return 0;
		});
		return { newState: state }
	}
}

window.storage = new Store(iniState, handlers)

As you can see above the handler job is to re-sort the tableDate by column name.

Let’s create our MetaComponent

// create the web component
class SortTable extends MetaComponent {
	constructor() {
		// bind storage to this component
		super(window.storage);
	}
	// get the columns names for the table
	getTableHeader() {
		// get the keys of the first element to map the table head names
		const hName = Object.keys(this.storage.getState().tableData[0])
		return Tr({}, () => {
			return hName.map(_th => {
				return Th({
					onclick: () => {
					// on click dispatch event change the sorting by this column
					this.storage.dispatch({type: 'CHANGE_SORT', sortBy: _th})
				}}, _th)
			})
		})
	}
	// get table content from the storage
	getTableBody() {
		const { tableData } = this.storage.getState();
		return tableData.map(tr => {
			return Tr({}, () => {
				return Object.entries(tr).map(_ent => {
					return Td({}, _ent[1])
				})
			})
		})
	}

	render() {
		const _TH = this.getTableHeader();
		const _TB = this.getTableBody();
		return Table({}, () => ([_TH, ..._TB ])); 
	}
	// change the content of the table on sort Action
	handleStoreEvents() {
		return {
		'CHANGE_SORT': () => {
			const table = this.querySelector('table');
			table.innerHTML = '';
			table.append(this.getTableHeader(), ...this.getTableBody())
		}
		}
	}
}
// define the custom element with a name
window.customElements.define('sort-table', SortTable);

now we can create our custom element as any HTMLElement

// get container element
const _cont = document.querySelector('#container');
// create new table
const _table = HTMLElementCreator('sort-table');
// append it to the container
_cont.appendChild(_table);

See this example running on codepen