gd-bs
Version:
Bootstrap JavaScript, TypeScript and Web Components library.
250 lines (212 loc) • 8.5 kB
text/typescript
import { ITable, ITableProps, ITableColumn } from "./types";
import { Base } from "../base";
import { HTML } from "./templates";
/**
* Table
*/
class _Table extends Base<ITableProps> implements ITable {
// Constructor
constructor(props: ITableProps, template: string = HTML) {
super(template, props);
// Configure the collapse
this.configure();
// Configure the parent
this.configureParent();
}
// Configure the card group
private configure() {
let hasFooter = false;
// See if columns are defined
let head = this.el.querySelector("thead");
if (head) {
if (this.props.columns) {
// Append the row
let row = document.createElement("tr");
head.appendChild(row);
// Parse the columns
for (let i = 0; i < this.props.columns.length; i++) {
let colProp = this.props.columns[i];
// Append the column
let column = document.createElement("th");
row.appendChild(column);
// See if the footer exists
if (colProp.footer || colProp.onRenderFooter) {
// Set the flag
hasFooter = true;
}
// Render the column
this.renderColumn(column, colProp);
}
// See if there is an event
if (this.props.onRenderHeaderRow) {
// Call the event
this.props.onRenderHeaderRow(row);
}
}
}
// Add the rows
this.addRows(this.props.rows);
// See if the footer exists
if (hasFooter) {
// Append the footer
let footer = document.createElement("tfoot");
this.el.appendChild(footer);
// Append the row
let row = document.createElement("tr");
footer.appendChild(row);
// Parse the columns
for (let i = 0; i < this.props.columns.length; i++) {
// Append the column
let column = document.createElement("td");
row.appendChild(column);
// Render the column
this.renderColumnFooter(column, this.props.columns[i]);
}
}
}
// Renders a cell
private renderCell(row: HTMLTableRowElement, props: ITableColumn, data, rowIdx: number) {
// Create the cell
let cell = document.createElement("td");
cell.className = props.className || "";
cell.innerHTML = data[props.name] == null ? "" : data[props.name];
row.appendChild(cell);
// See if there is a scope
if (props.scope) {
// Set the scope
cell.setAttribute("scope", props.scope);
}
// See if there is an event for this column
if (props.onRenderCell) {
// Call the event
props.onRenderCell(cell, props, data, rowIdx);
}
// See if there is an event for this component
if (this.props.onRenderCell) {
// Call the event
this.props.onRenderCell(cell, props, data, rowIdx);
}
// See if there is a click event
if (props.onClickCell || this.props.onClickCell) {
// Add the click event
cell.addEventListener("click", ev => {
// Call the event
props.onClickCell ? props.onClickCell(cell, props, data, rowIdx) : null;
this.props.onClickCell ? this.props.onClickCell(cell, props, data, rowIdx) : null;
});
}
}
// Renders a column
private renderColumn(column: HTMLTableCellElement, props: ITableColumn) {
column.innerHTML = props.isHidden ? "" : props.title || props.name;
column.setAttribute("scope", "col");
// See if there is an event for this column
if (props.onRenderHeader) {
// Call the event
props.onRenderHeader(column, props);
}
// See if there is an event for this component
if (this.props.onRenderHeaderCell) {
// Call the event
this.props.onRenderHeaderCell(column, props);
}
// See if there is a click event
if (props.onClickHeader || this.props.onClickHeader) {
// Add the click event
column.addEventListener("click", ev => {
// Call the event
props.onClickHeader ? props.onClickHeader(column, props) : null;
this.props.onClickHeader ? this.props.onClickHeader(column, props) : null;
});
}
}
// Renders a column footer
private renderColumnFooter(column: HTMLTableCellElement, props: ITableColumn) {
column.innerHTML = props.footer || "";
// See if there is an event for this column
if (props.onRenderFooter) {
// Call the event
props.onRenderFooter(column, props);
}
// See if there is an event for this component
if (this.props.onRenderFooterCell) {
// Call the event
this.props.onRenderFooterCell(column, props);
}
// See if there is a click event
if (props.onClickFooter || this.props.onClickFooter) {
// Add the click event
column.addEventListener("click", ev => {
// Call the event
props.onClickFooter ? props.onClickFooter(column, props) : null;
this.props.onClickFooter ? this.props.onClickFooter(column, props) : null;
});
}
}
// Renders a row
private renderRow(row: HTMLTableRowElement, data, rowIdx: number) {
// Parse the columns
for (let i = 0; i < this.props.columns.length; i++) {
// Create the cell
this.renderCell(row, this.props.columns[i], data, rowIdx);
}
// See if there is an event
if (this.props.onRenderRow) {
// Call the event
this.props.onRenderRow(row, data, rowIdx);
}
}
/**
* Public Interface
*/
// Method to add the rows
addRows(rows: Array<any> = []) {
let tbody = this.el.querySelector("tbody");
if (tbody) {
// Parse the rows
for (let i = 0; i < rows.length; i++) {
// Create the row
let row = document.createElement("tr");
tbody.appendChild(row);
// Render the row
this.renderRow(row, rows[i], i);
}
}
}
// Method to update a column element
updateColumn(elCol: HTMLElement, colIdx: number, row: any) {
// Get the column
let colProps = this.props.columns[colIdx];
if (colProps) {
// Set the value
elCol.innerHTML = row[colProps.name] == null ? "" : row[colProps.name];
// See if there is an event for this column
if (colProps.onRenderCell) {
// Call the event
colProps.onRenderCell(elCol as HTMLTableCellElement, colProps, row);
}
// See if there is an event for this component
if (this.props.onRenderCell) {
// Call the event
this.props.onRenderCell(elCol as HTMLTableCellElement, colProps, row);
}
}
}
// Method to update a row element
updateRow(elRow: HTMLElement, row: any) {
// Parse the columns
for (let i = 0; i < this.props.columns.length; i++) {
let elCol = elRow.children[i] as HTMLElement;
if (elCol) {
// Update the column
this.updateColumn(elCol, i, row);
}
}
// See if there is an event
if (this.props.onRenderRow) {
// Call the event
this.props.onRenderRow(elRow as HTMLTableRowElement, row);
}
}
}
export const Table = (props: ITableProps, template?: string): ITable => { return new _Table(props, template); }