DefinitelyTyped/types/react-bootstrap-table/react-bootstrap-table-tests.tsx
2019-04-16 15:29:21 -07:00

1574 lines
59 KiB
TypeScript

import * as React from 'react';
import { render } from 'react-dom';
import {
BootstrapTable,
ButtonGroupProps,
CellEdit,
ColumnDescription,
CustomFilter,
CustomSelectProps,
DeleteButton,
EditableAttrs,
EditValidatorObject,
ExpandColumnComponentProps,
ExpandColumnOptions,
ExportCSVButton,
Filter,
FilterData,
FilterType,
FooterData,
InsertButton,
InsertModalColumnDescription,
InsertModalFooter,
InsertModalHeader,
ModalBodyInterface,
Options,
PaginationPanelProps,
SearchField,
SearchFieldInterface,
SearchFieldProps,
SearchPanelProps,
SelectRow,
ShowSelectedOnlyButton,
SizePerPageDropDown,
SortOrder,
TableHeaderColumn,
ToolBarProps,
CustomFilterParameters
} from 'react-bootstrap-table';
interface Product {
id: number;
name: string;
price?: number;
quality?: number;
inStockStatus?: number;
sales?: number;
}
const products: Product[] = [{
id: 1,
name: "Item name 1",
price: 100
}, {
id: 2,
name: "Item name 2",
price: 100
}];
type JobType = 'A' | 'B' | 'C' | 'D';
interface Job {
id: number;
status: string;
name: string;
type: JobType;
active: 'Y' | 'N';
}
const jobs = [
{ id: 1, status: '200', name: 'Item name 1', type: 'B', active: 'N' },
{ id: 2, status: '200', name: 'Item name 2', type: 'B', active: 'Y' }
];
const jobTypes = ['A', 'B', 'C', 'D'];
interface ExtendedJob {
id: number;
name: string;
type1: JobType;
type2: JobType;
active: 'Y' | 'N';
datetime: Date;
}
const extendedJobs = [
{ id: 1, name: 'Item name 1', type1: 'A', type2: 'B', active: 'N', datetime: '2001-12-28T14:57:00' },
{ id: 2, name: 'Item name 2', type1: 'A', type2: 'B', active: 'Y', datetime: '2002-12-28T14:57:00' }
];
const inStockStatus = {
1: 'yes',
2: 'no'
};
// It's a data format example.
function priceFormatter(cell: number, row: Product) {
return '<i class="glyphicon glyphicon-usd"></i> ' + cell;
}
render(
<BootstrapTable data={products} striped={true} hover={true} ignoreSinglePage>
<TableHeaderColumn dataField="id" isKey={true} dataAlign="center" dataSort={true}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField="name" dataSort={true} editable={{ type: 'textarea', rows: 10 }}>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField="price" dataFormat={priceFormatter}>Product Price</TableHeaderColumn>
</BootstrapTable>,
document.getElementById("app")
);
const qualityType = {
0: 'good',
1: 'bad',
2: 'unknown'
};
function enumFormatter(cell: any, row: any, enumObject: any, rowIndex: number) {
console.log(`The row index: ${rowIndex}`);
return enumObject[cell];
}
class SelectFilterWithDefaultValue extends React.Component {
render() {
return (
<BootstrapTable data={products}>
<TableHeaderColumn dataField='id' isKey>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='quality' filterFormatted dataFormat={enumFormatter}
formatExtraData={qualityType} filter={{ type: 'SelectFilter', options: qualityType, defaultValue: 1 }}>Product Quality</TableHeaderColumn>
</BootstrapTable>
);
}
}
class TextFilterWithCondition extends React.Component {
render() {
return (
<BootstrapTable data={products}>
<TableHeaderColumn dataField='id' isKey>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name' filter={{ type: 'TextFilter', delay: 1000, condition: 'eq' }}>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>
);
}
}
interface CustomFilterParams {
textOK: string;
textNOK: string;
}
function getCustomFilter(filterHandler: (parameters?: CustomFilterParameters<CustomFilterParams>, type?: 'CustomFilter') => void, customFilterParameters: CustomFilterParameters<CustomFilterParams>) {
return (
<div />
);
}
function customFilterCallback(cell: any, callbackParameters: CustomFilterParams) { return true; }
class CustomFilterTable extends React.Component {
render() {
const filter: Filter = { type: 'CustomFilter', getElement: getCustomFilter, customFilterParameters: { callback: customFilterCallback, callbackParameters: { textOK: 'yes', textNOK: 'no' }} };
return (
<BootstrapTable data={products}>
<TableHeaderColumn dataField='id' isKey>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='isInStock' filter={filter}>Product Is In Stock</TableHeaderColumn>
</BootstrapTable>
);
}
}
class RemotePropsDefault extends React.Component {
render() {
const filter: CustomFilter = { type: 'CustomFilter', getElement: getCustomFilter, customFilterParameters: { callback: customFilterCallback, callbackParameters: { textOK: 'yes', textNOK: 'no' }} };
return (
<BootstrapTable
data={products}
remote={(remoteObj) => {
remoteObj.cellEdit = true;
return remoteObj;
}}
options={{
onCellEdit: (row: any, fieldName: string, value: any) => { console.info(row); return value; }
}}
>
<TableHeaderColumn dataField='id' isKey>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='isInStock' filter={filter}>Product Is In Stock</TableHeaderColumn>
</BootstrapTable>
);
}
}
class RemotePropsSpecified extends React.Component {
render() {
const filter: CustomFilter<CustomFilterParams> = {
type: 'CustomFilter',
getElement: getCustomFilter,
customFilterParameters: {
callback: customFilterCallback,
callbackParameters: { textOK: 'yes', textNOK: 'no' }
}
};
return (
<BootstrapTable
data={products}
remote={(remoteObj) => {
remoteObj.cellEdit = true;
return remoteObj;
}}
options={{
onCellEdit: (row: any, fieldName: string, value: any) => { console.info(row); return value; }
}}
>
<TableHeaderColumn dataField='id' isKey>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='isInStock' filter={filter}>Product Is In Stock</TableHeaderColumn>
</BootstrapTable>
);
}
}
class RemoteBool extends React.Component {
render() {
const filter: Filter = { type: 'CustomFilter', getElement: getCustomFilter, customFilterParameters: {callback: customFilterCallback, callbackParameters: { textOK: 'yes', textNOK: 'no' } }};
return (
<BootstrapTable
data={products}
remote
>
<TableHeaderColumn dataField='id' isKey>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='isInStock' filter={filter}>Product Is In Stock</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* See http://allenfang.github.io/react-bootstrap-table/docs.html#tdAttr
*/
const tdAttrExample = <BootstrapTable data={ products } search>
<TableHeaderColumn dataField='id' isKey>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name' tdAttr={ { "data-attr": 'test' } }>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>;
/**
* See http://allenfang.github.io/react-bootstrap-table/docs.html#tdStyle
*/
const tdStyleExample = <BootstrapTable data={ products } search>
<TableHeaderColumn dataField='id' isKey>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name' tdStyle={ { whiteSpace: 'normal' } }>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>;
/**
* See http://allenfang.github.io/react-bootstrap-table/docs.html#thStyle
*/
const thStyleExample = <BootstrapTable data={ products } search>
<TableHeaderColumn dataField='id' isKey>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name' thStyle={ { fontWeight: 'lighter' } }>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>;
/**
* Adopted from https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/column-header-span/column-header-span-complex.js
*/
class ColumnHeaderSpanComplex extends React.Component {
render() {
const options: Options = { exportCSVSeparator: '##' };
return (
<BootstrapTable data={products} insertRow deleteRow exportCSV options={options}>
<TableHeaderColumn row={0} rowSpan={2} dataField='id' isKey={true} >ID</TableHeaderColumn>
<TableHeaderColumn row={0} colSpan={3} dataSort csvHeader='Product' headerAlign='right'>Product</TableHeaderColumn>
<TableHeaderColumn row={1} dataField='name' width='175' dataAlign='center'>name</TableHeaderColumn>
<TableHeaderColumn row={1} dataField='price' dataSort>price</TableHeaderColumn>
<TableHeaderColumn row={1} dataField='coupon' width='70'>Coupon</TableHeaderColumn>
<TableHeaderColumn row={0} csvHeader='In stock' rowSpan={2} dataField='status' export={false}>In stock</TableHeaderColumn>
<TableHeaderColumn row={0} colSpan={2} csvHeader='Customer' filter={{ type: 'TextFilter', delay: 1000 }}>Customer</TableHeaderColumn>
<TableHeaderColumn row={1} csvHeader='name' dataField='customer'>name</TableHeaderColumn>
<TableHeaderColumn row={1} csvHeader='order' dataField='order' dataSort>order</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Pagination options
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/pagination/custom-pagination-table.js
*/
class PaginationTable extends React.Component {
sizePerPageListChange = (sizePerPage: number) => {
alert(`sizePerPage: ${sizePerPage}`);
}
onPageChange = (page: number, sizePerPage: number) => {
alert(`page: ${page}, sizePerPage: ${sizePerPage}`);
}
renderShowsTotal = (start: number, to: number, total: number) => {
return (
<p style={{ color: 'blue' }}>
From {start} to {to}, totals is {total}&nbsp;&nbsp;(its a customize text)
</p>
);
}
render() {
const options: Options<Product> = {
onPageChange: this.onPageChange,
onSizePerPageList: this.sizePerPageListChange,
page: 2, // which page you want to show as default
sizePerPageList: [{
text: '5', value: 5
}, {
text: '10', value: 10
}, {
text: 'All', value: products.length
}], // you can change the dropdown list for size per page
sizePerPage: 5, // which size per page you want to locate as default
pageStartIndex: 0, // where to start counting the pages
paginationSize: 3, // the pagination bar size.
prePage: 'Prev', // Previous page button text
nextPage: 'Next', // Next page button text
firstPage: 'First', // First page button text
lastPage: 'Last', // Last page button text
prePageTitle: 'Go to previous', // Previous page button title
nextPageTitle: 'Go to next', // Next page button title
firstPageTitle: 'Go to first', // First page button title
lastPageTitle: 'Go to Last', // Last page button title
paginationShowsTotal: this.renderShowsTotal, // Accept bool or function
paginationPosition: 'top', // default is bottom, top and both is all available
keepSizePerPageState: true, // default is false, enable will keep sizePerPage dropdown state(open/clode) when external rerender happened
hideSizePerPage: true, // You can hide the dropdown for sizePerPage
alwaysShowAllBtns: true, // Always show next and previous button
withFirstAndLast: false, // Hide the going to First and Last page button
hidePageListOnlyOnePage: true // Hide the page list if only one page.
};
return (
<BootstrapTable data={products} pagination={true} options={options}>
<TableHeaderColumn dataField='id' isKey={true}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Adopted from https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/cell-edit/blur-to-escape-table.js
*/
class BlurToEscapeTable extends React.Component {
render() {
const cellEditProp: CellEdit<Product> = {
mode: 'click',
blurToEscape: true
};
return (
<BootstrapTable data={products} cellEdit={cellEditProp} striped={true} hover={true} condensed={true} bordered={false}>
<TableHeaderColumn width='150px' dataField='id' isKey={true}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Cell classnames, row saving hooks.
* @see https://githum.com/AllenFang/react-bootstrap-table/blob/master/examples/js/cell-edit/cell-edit-classname.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/cell-edit/cell-edit-hook-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/manipulation/insert-row-table.js
*/
class EditCellClassNameTable extends React.Component {
jobNameValidator = (value: string) => {
const response: EditValidatorObject = { isValid: true, notification: { type: 'success', msg: '', title: '' } };
if (!value) {
response.isValid = false;
response.notification.type = 'error';
response.notification.msg = 'Value must be inserted';
response.notification.title = 'Requested Value';
} else if (value.length < 10) {
response.isValid = false;
response.notification.type = 'error';
response.notification.msg = 'Value must have 10+ characters';
response.notification.title = 'Invalid Value';
}
return response;
}
jobStatusValidator = (value: string) => {
const nan = isNaN(parseInt(value, 10));
if (nan) {
return 'Job Status must be a integer!';
}
return true;
}
invalidJobStatus = (cell: string, row: Job) => {
console.log(`${cell} at row id: ${row.id} fails on editing`);
return 'invalid-jobstatus-class';
}
editingJobStatus = (cell: string, row: Job) => {
console.log(`${cell} at row id: ${row.id} in current editing`);
return 'editing-jobstatus-class';
}
onBeforeSaveCellAsync = <K extends keyof Job>(row: Job, cellName: K, cellValue: Job[K], done: (ok: boolean) => void): boolean | 1 => {
setTimeout(() => {
done(false); // it's not ok to save :(
}, 3000);
return 1; // return 1 === async operation.
}
onAfterSaveCell(row: Job, cellName: string, cellValue: any) {
alert(`Save cell ${cellName} with value ${cellValue}`);
let rowStr = '';
for (const prop in row) {
rowStr += `${prop}: ${row[prop as keyof Job]}\n`;
}
alert('The whole row :\n' + rowStr);
}
onAfterInsertRow = (row: any) => {
let newRowStr = '';
for (const prop in row) {
newRowStr += `${prop}: ${row[prop]} \n`;
}
alert('The new row is:\n ' + newRowStr);
}
render() {
const cellEditProp: CellEdit<Job> = {
mode: 'dbclick',
blurToSave: true,
beforeSaveCell: this.onBeforeSaveCellAsync,
afterSaveCell: this.onAfterSaveCell
};
const options: Options<Job> = {
afterInsertRow: this.onAfterInsertRow // A hook for after insert rows
};
return (
<BootstrapTable data={jobs} cellEdit={cellEditProp} insertRow={true} options={options}>
<TableHeaderColumn dataField='id' isKey={true} editable={false}>Job ID</TableHeaderColumn>
<TableHeaderColumn dataField='status' editable={{ validator: this.jobStatusValidator }}
editColumnClassName={this.editingJobStatus} invalidEditColumnClassName={this.invalidJobStatus}>Job Status</TableHeaderColumn>
<TableHeaderColumn dataField='name' editable={{ type: 'textarea', validator: this.jobNameValidator }}
editColumnClassName='editing-jobsname-class' invalidEditColumnClassName='invalid-jobsname-class'>Job Name</TableHeaderColumn>
<TableHeaderColumn dataField='type' editable={{ type: 'select', options: { values: jobTypes } }}>Job Type</TableHeaderColumn>
<TableHeaderColumn dataField='active' editable={{ type: 'checkbox', options: { values: 'Y:N' } }}>Active</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Multiple field sorting, filtering, searching and clearing
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/manipulation/filter-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/manipulation/multi-search-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/manipulation/search-clear-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/manipulation/strict-multi-search-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/remote/remote-store-search.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/sort/custom-caret-sort-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/sort/custom-sort-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/sort/sort-style-table.js
*/
class MultiSortAndFiltering extends React.Component {
tableRef: BootstrapTable | null;
idRef: TableHeaderColumn | null;
state = { data: products };
onSortChange = (name: string, order: SortOrder) => {
console.log(`Next sort = ${name}:${order}`);
}
cleanSort = () => { this.tableRef.cleanSort(); };
cleanSelected = () => { this.tableRef.cleanSelected(); };
onFilterChange = (filter: FilterData) => {
Object.keys(filter).forEach((column) => {
console.log(`Filtering ${column}: ${JSON.stringify(filter[column])}`);
});
}
cleanFilters = () => { this.idRef.cleanFiltered(); };
afterColumnFilter = (filterConds: ReadonlyArray<FilterData>, result: ReadonlyArray<Product>) => {
console.log('Filter Conditions: ');
filterConds.forEach((filterCond: FilterData) => {
Object.keys(filterCond).forEach((fieldName: string) =>
console.log(`Filter column = ${fieldName}, Filter value = ${filterCond[fieldName]}`));
});
console.log('Result is:');
for (const resultItem of result) {
console.log(`Product: ${resultItem.id}, ${resultItem.name}, ${resultItem.price}`);
}
}
onSearchChange = (searchText: string, colInfos: ReadonlyArray<ColumnDescription<Product>>, multiColumnSearch: boolean) => {
this.setState({ data: products.filter((product) => product.name = searchText) });
}
afterSearch = (searchText: string, result: ReadonlyArray<Product>) => {
console.log(`Your search text is ${searchText}`);
console.log('Result is:');
for (const resultItem of result) {
console.log(`Product: ${resultItem.id}, ${resultItem.name}, ${resultItem.price}`);
}
}
getNameCaret = (direction: SortOrder | null, fieldName: string) =>
(direction === 'asc')
? (<span> up</span>)
: (direction === 'desc')
? (<span> down</span>)
: (<span> up/down</span>)
revertSortFunc = (a: Product, b: Product, order: SortOrder) =>
(order === 'desc') ? a.price - b.price : b.price - a.price
customSortStyle = (order: SortOrder, dataField: string) =>
(order === 'desc') ? 'sort-desc' : 'sort-asc'
render() {
const options: Options<Product> = {
onSortChange: this.onSortChange,
onFilterChange: this.onFilterChange,
noDataText: 'This is custom text for empty data',
withoutNoDataText: false,
afterColumnFilter: this.afterColumnFilter,
onSearchChange: this.onSearchChange,
afterSearch: this.afterSearch,
clearSearch: true,
sortIndicator: true
};
return (
<div>
<button className='btn ben-default' onClick={this.cleanSort}>Clean</button>
<BootstrapTable data={this.state.data} options={options} multiColumnSort={2}
multiColumnSearch={true} scrollTop={'Bottom'} strictSearch={true} fetchInfo={{ dataTotalSize: 5 }}>
<TableHeaderColumn dataField='id' isKey={true} searchable={false} dataSort={true}
filter={{ type: 'TextFilter', delay: 500 }} sortHeaderColumnClassName='sorted'>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name' defaultASC={true} dataSort={true} caretRender={this.getNameCaret}
sortHeaderColumnClassName={this.customSortStyle}>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price' sortFunc={this.revertSortFunc}
filter={{ type: 'NumberFilter', options: [10, 50, 100], numberComparators: ['>=', '<=', '='] }}>Product Price</TableHeaderColumn>
</BootstrapTable>
</div>
);
}
}
/**
* Sort with extra data.
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/sort/custom-sort-with-extra-data-table.js
*/
class CustomSortWithExtraDataTable extends React.Component {
sortByName = (a: any, b: any, order: SortOrder, field: string, enumObject: any) => {
if (order === 'desc') {
if (enumObject[a[field]] > enumObject[b[field]]) {
return -1;
} else if (enumObject[a[field]] < enumObject[b[field]]) {
return 1;
}
return 0;
}
if (enumObject[a[field]] < enumObject[b[field]]) {
return -1;
} else if (enumObject[a[field]] > enumObject[b[field]]) {
return 1;
}
return 0;
}
render() {
return (
<BootstrapTable data={products}>
<TableHeaderColumn dataField='id' isKey={true}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='quality'
dataFormat={enumFormatter} formatExtraData={qualityType}
dataSort={true}
sortFunc={this.sortByName} sortFuncExtraData={qualityType}>
Product Quality</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Render custom pagination with provided SizePerPageDropDown component.
*/
class CustomPagination extends React.Component {
renderPagination = (props: PaginationPanelProps) => (
<div>
<SizePerPageDropDown variation='dropup' options={props.sizePerPageList} btnContextual='primary' currSizePerPage={props.sizePerPage.toString()} />
<div>
<button onClick={() => props.changeSizePerPage(25)} className='btn btn-default'>Click to force size per page as 25</button>
<button onClick={() => props.toggleDropDown()} className='btn btn-default'>Click to force toggle dropdown</button>
<button onClick={() => props.changePage(3)} className='btn btn-default'>Jump to page 3</button>
</div>
</div>
)
render() {
const options: Options = {
paginationPanel: this.renderPagination
};
return (
<BootstrapTable data={products} options={options} pagination>
<TableHeaderColumn dataField='id' />
<TableHeaderColumn dataField='name' />
<TableHeaderColumn dataField='price' />
</BootstrapTable>
);
}
}
/**
* Customize the entire insert modal.
* Adapted from https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/custom/insert-modal/custom-insert-modal.js
*/
class CustomModal extends React.Component {
handleSaveBtnClick = (columns: ReadonlyArray<InsertModalColumnDescription<Product>>, onSave: (row: any) => void) => {
const newRow: {[field: string]: string} = {};
columns.forEach((column, i) => {
newRow[column.field] = (this.refs[column.field] as HTMLInputElement).value;
}, this);
onSave(newRow);
}
createCustomModal = (
onModalClose: () => void,
onSave: (row: any) => void,
columns: ReadonlyArray<InsertModalColumnDescription<Product>>,
validateState: { [dataField: string]: string },
ignoreEditable: boolean
) => (
<div style={{ backgroundColor: '#eeeeee' }} className='modal-content'>
<h2 style={{ color: 'red' }}>Custom Insert Modal</h2>
<div>
{
columns.map((column, i) => {
const {
editable,
format,
field,
name,
hiddenOnInsert
} = column;
if (hiddenOnInsert) {
return null;
}
const error = validateState[field] ?
(<span className='help-block bg-danger'>{validateState[field]}</span>) :
null;
return (
<div className='form-group' key={field}>
<label>{name} : </label>
<input ref={field} type='text' defaultValue={''} />
{error}
</div>
);
})
}
</div>
<div>
<button className='btn btn-danger' onClick={onModalClose}>Leave</button>
<button className='btn btn-success' onClick={(e) => this.handleSaveBtnClick(columns, onSave)}>Confirm</button>
</div>
</div>
)
render() {
const options: Options<Product> = {
insertModal: this.createCustomModal
};
return (
<BootstrapTable data={products} options={options} insertRow>
<TableHeaderColumn dataField='id' isKey={true}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Custom Insert Modal Fields, both as a custom component and as custom fields.
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/custom/insert-modal/custom-insert-modal-field.js
*/
class SalesRadioField extends React.Component<{editorClass: string, ignoreEditable: boolean}> {
yes: HTMLInputElement | null;
no: HTMLInputElement | null;
getFieldValue = () => {
return this.yes.checked ? 'Yes' : 'No';
}
render() {
return (
<div>
<label className='radio-inline'>
<input ref={(node) => { this.yes = node; }} type='radio' name='optradio' value='Yes' />Yes
</label>
<label className='radio-inline'>
<input ref={(node) => { this.no = node; }} type='radio' name='optradio' value='No' />No
</label>
</div>
);
}
}
class CustomInsertModalFieldTable extends React.Component {
customKeyField = (
column: InsertModalColumnDescription<Product>,
attr: EditableAttrs,
editorClass: string,
ignoreEditable: boolean
) => {
const seqId = products.length;
return (
<input type='text' { ...attr } disabled value={seqId} className={`${editorClass}`} />
);
}
customNameField = (
column: InsertModalColumnDescription<Product>,
attr: EditableAttrs,
editorClass: string,
ignoreEditable: boolean,
defaultValue: any) => {
const fruits = ['banana', 'apple', 'orange', 'tomato', 'strawberries'];
return (
<select className={`${editorClass}`} { ...attr }>
{
fruits.map(name => (<option key={name} value={name}>{name}</option>))
}
</select>
);
}
customSaleField = (
column: InsertModalColumnDescription<Product>,
attr: EditableAttrs,
editorClass: string,
ignoreEditable: boolean,
defaultValue: any) => {
return (
<SalesRadioField ref={attr.ref} editorClass={editorClass} ignoreEditable={ignoreEditable} />
);
}
render() {
return (
<BootstrapTable ref='table' data={products} insertRow={true}>
<TableHeaderColumn dataField='id' isKey={true} customInsertEditor={{ getElement: this.customKeyField }}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name' customInsertEditor={{ getElement: this.customNameField }}>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='sales' customInsertEditor={{ getElement: this.customSaleField }}>On Sales?</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Custom modal header, body & footer.
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/custom/insert-modal/default-custom-insert-modal-header.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/custom/insert-modal/custom-insert-modal-body.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/custom/insert-modal/default-custom-insert-modal-footer.js
*/
interface MyCustomBodyProps {
columns: ReadonlyArray<InsertModalColumnDescription<Product>>;
validateState: { [dataField: string]: string };
ignoreEditable: boolean;
}
class MyCustomBody extends React.Component<MyCustomBodyProps> implements ModalBodyInterface<Product> {
getFieldValue() {
const newRow: Partial<Product> = {};
this.props.columns.forEach((column, i) => {
newRow[column.field] = (this.refs[column.field] as HTMLInputElement).value as number & string;
}, this);
return newRow as Product;
}
render() {
const { columns, validateState } = this.props;
return (
<div className='modal-body'>
<h2 style={{ color: 'red' }}>Custom body</h2>
<div>
{
this.props.columns.map((column, i) => {
const {
editable,
format,
field,
name,
hiddenOnInsert
} = column;
if (hiddenOnInsert) {
return null;
}
const error = validateState[field] ?
(<span className='help-block bg-danger'>{validateState[field]}</span>) :
null;
return (
<div className='form-group' key={field}>
<label>{name}</label>
<input ref={field} type='text' defaultValue={''} />
{error}
</div>
);
})
}
</div>
</div>
);
}
}
class DefaultCustomInsertModalHeaderFooterTable extends React.Component {
createCustomModalFooter = (closeModal: () => void, save: () => void) => {
return (
<InsertModalFooter
className='my-custom-class'
saveBtnText='CustomSaveText'
closeBtnText='CustomCloseText'
closeBtnContextual='btn-warning'
saveBtnContextual='btn-success'
closeBtnClass='my-close-btn-class'
saveBtnClass='my-save-btn-class'
beforeClose={(e) => {}}
beforeSave={(e) => {}}
onModalClose={closeModal}
onSave={save} />
);
}
createCustomModalHeader = (closeModal: () => void, save: () => void) => {
return (
<InsertModalHeader
className='my-custom-class'
title='This is my custom title'
beforeClose={(e) => { }}
onModalClose={closeModal}
hideClose={true} />
);
}
createCustomModalBody = (
columns: ReadonlyArray<InsertModalColumnDescription<Product>>,
validateState: { [dataField: string]: string },
ignoreEditable: boolean
) => (
<MyCustomBody
columns={columns}
validateState={validateState}
ignoreEditable={ignoreEditable}
/>
)
render() {
const options: Options<Product> = {
insertModalFooter: this.createCustomModalFooter,
insertModalHeader: this.createCustomModalHeader,
insertModalBody: this.createCustomModalBody
};
return (
<BootstrapTable data={products} options={options} insertRow={true}>
<TableHeaderColumn dataField='id' isKey={true}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Custom Toolbar, including Search Panel & Buttons, and custom delete confirmation.
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/custom/toolbar/custom-button-group.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/custom/toolbar/custom-toolbar-1.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/custom/search/default-custom-search-field.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/custom/search/custom-search-panel-1.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/custom/search/fully-custom-search-field.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/custom/insert-button/default-custom-insert-button.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/custom/delete-button/default-custom-delete-button.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/custom/csv-button/default-custom-csv-button.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/manipulation/del-row-custom-confirm.js
*/
class MySearchField extends React.Component<SearchFieldProps> implements SearchFieldInterface {
field: SearchField | null;
getValue() {
return this.field.getValue();
}
setValue(search: string) {
this.field.setValue(search);
}
render() {
const { ...rest} = this.props;
return (
<SearchField
className={this.props.className}
defaultValue={this.props.defaultValue}
placeholder={this.props.placeholder}
onKeyUp={this.props.onKeyUp}
ref={(node) => { this.field = node; }}
/>
);
}
}
class CustomButtonGroup extends React.Component {
createInsertButton = (onClick: (e: React.MouseEvent<{}>) => void) => (
<InsertButton
btnText='CustomInsertText'
btnContextual='btn-warning'
className='my-custom-class'
btnGlyphicon='glyphicon-edit'
onClick={onClick} />
)
createDeleteButton = (onClick: (e: React.MouseEvent<{}>) => void) => (
<DeleteButton
btnText='CustomDeleteText'
btnContextual='btn-danger'
className='my-custom-class'
btnGlyphicon='glyphicon-edit'
onClick={onClick} />
)
createExportCSVButton = (onClick: (e: React.MouseEvent<{}>) => void) => (
<ExportCSVButton
btnText='CustomExportText'
btnContextual='btn-danger'
className='my-custom-class'
btnGlyphicon='glyphicon-edit'
onClick={onClick} />
)
createShowSelectedOnlyButton = (onClick: (e: React.MouseEvent<{}>) => void, showSelected: boolean) => (
<ShowSelectedOnlyButton
showAllText='Show All'
showOnlySelectText='Show Selected'
btnContextual='btn-info'
className='my-custom-class'
onClick={onClick} />
)
createCustomButtonGroup = (props: ButtonGroupProps) => (
<div className='my-custom-class'>
{props.showSelectedOnlyBtn}
{props.exportCSVBtn}
{props.insertBtn}
{props.deleteBtn}
<button type='button'
className={`btn btn-primary`}>
MyCustomBtn
</button>
</div>
)
createCustomSearchField = (props: SearchFieldProps) => (
<MySearchField
className='my-custom-class'
defaultValue={props.defaultValue}
placeholder={props.placeholder}
onKeyUp={props.onKeyUp}
/>
)
createCustomClearSearch = (onClick: (e: React.MouseEvent<{}>) => void) => (
<button
className='btn btn-success'
onClick={onClick}>
Clear Search
</button>
)
createCustomSearchPanel = (props: SearchPanelProps) => (
<div>
<div className='input-group'>
<span className='input-group-btn'>
{props.clearBtn}
</span>
</div>
{props.searchField}
</div>
)
createCustomToolBar = (props: ToolBarProps) => {
return (
<div style={{ margin: '15px' }}>
{props.components.btnGroup}
<div className='col-xs-8 col-sm-4 col-md-4 col-lg-2'>
{props.components.searchPanel}
</div>
</div>
);
}
customConfirm = (next: () => void, dropRowKeys: ReadonlyArray<number>) => {
const dropRowKeysStr = dropRowKeys.join(',');
if (confirm(`(It's a custom confirm)Are you sure you want to delete ${dropRowKeysStr}?`)) {
next();
}
}
render() {
const selectRow: SelectRow = {
mode: 'checkbox',
showOnlySelected: true
};
const options: Options<Product> = {
insertBtn: this.createInsertButton,
deleteBtn: this.createDeleteButton,
exportCSVBtn: this.createExportCSVButton,
showSelectedOnlyBtn: this.createShowSelectedOnlyButton,
btnGroup: this.createCustomButtonGroup,
clearSearch: true,
clearSearchBtn: this.createCustomClearSearch,
searchField: this.createCustomSearchField,
searchPanel: this.createCustomSearchPanel,
toolBar: this.createCustomToolBar,
searchDelayTime: 3000,
handleConfirmDeleteRow: this.customConfirm
};
return (
<BootstrapTable data={products}
options={options}
selectRow={selectRow}
insertRow={true}
deleteRow={true}
exportCSV={true}
search={true}>
<TableHeaderColumn dataField='id' isKey={true}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Expanding Rows & Selection
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/expandRow/expand-row-by-column.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/expandRow/expand-row-with-selection.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/expandRow/custom-expand-indicator.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/expandRow/custom-expand-class.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/expandRow/auto-collapse.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/expandRow/manage-expanding.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/selection/all-select.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/selection/custom-multi-select-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/selection/default-select-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/selection/select-bgcolor-dynamic-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/selection/select-filter-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/selection/select-hook-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/selection/select-row-class-table.js
*/
class ExpandRowExample extends React.Component<{}, {expanding: number[]}> {
isExpandableRow = (row: any) => row.id === 2;
expandComponent = (row: any) => (
<div>You expanded the row.</div>
)
expandColumnComponent = ({ isExpandableRow, isExpanded }: ExpandColumnComponentProps) => {
const content = isExpandableRow
? (isExpanded ? '(-)' : '(+)')
: ' ';
return (
<div> {content} </div>
);
}
handleExpand = (rowKey: number, isExpand: boolean) => {
if (isExpand) {
this.setState({ expanding: [...this.state.expanding] });
} else {
this.setState({ expanding: [...this.state.expanding.filter(id => id !== rowKey)] });
}
}
onSelectAll = (isSelected: boolean) => (isSelected) ? products.map(row => row.id) : [];
onSelect = (row: Product, isSelected: boolean, e: React.MouseEvent<any>, rowIndex: number) => {
const rowStr = `id: "${row.id}", name: ${row.name}, price: ${row.price}`;
console.log(e);
alert(`Selected: ${isSelected}, rowIndex: ${rowIndex}, row: ${rowStr}`);
}
customMultiSelect = (props: CustomSelectProps) => (
<div className='checkbox-personalized'>
<input
type={props.type}
name={'checkbox' + props.rowIndex}
id={'checkbox' + props.rowIndex}
checked={props.checked}
disabled={props.disabled}
onChange={e => props.onChange(e, props.rowIndex)}
ref={input => {
if (input) {
input.indeterminate = props.indeterminate;
}
}} />
<label htmlFor={'checkbox' + props.rowIndex}>
<div className='check'></div>
</label>
</div>
)
selectedRowClass = (row: Product, isSelect: boolean) =>
(isSelect)
? ((row.id >= 3) ? 'bigger-than-three-select-row' : 'less-than-three-select-row')
: ''
render() {
const options: Options<Product> = {
expandRowBgColor: 'rgb(242, 255, 163)',
expandBy: 'column',
onlyOneExpanding: true,
expanding: this.state.expanding,
onExpand: this.handleExpand,
expandParentClass: 'custom-expand-parent',
expandBodyClass: (row, rowIndex, isExpanding) => {
return (!isExpanding)
? 'current-is-hidden'
: (rowIndex > 1)
? 'custom-expand-body-1'
: 'custom-expand-body-0';
}
};
const selectRow: SelectRow<Product> = {
mode: 'checkbox',
bgColor: (row: Product, isSelect: boolean) =>
(isSelect)
? ((row.id < 2) ? 'blue' : ((row.id < 4) ? 'red' : 'yellow'))
: null,
clickToSelect: true, // click to select, default is false
clickToExpand: true, // click to expand row, default is false
onSelect: this.onSelect,
onSelectAll: this.onSelectAll,
customComponent: this.customMultiSelect,
hideSelectColumn: false,
selected: [0, 2],
showOnlySelected: true,
onlyUnselectVisible: true,
className: this.selectedRowClass,
columnWidth: '60px',
unselectable: [1, 3]
};
const expandColumnOptions: ExpandColumnOptions = {
expandColumnVisible: true,
expandColumnBeforeSelectColumn: false,
expandColumnComponent: this.expandColumnComponent,
columnWidth: 50
};
return (
<BootstrapTable data={products}
options={options}
expandableRow={this.isExpandableRow}
expandComponent={this.expandComponent}
expandColumnOptions={expandColumnOptions}
autoCollapse={{ sort: true, search: true, filter: true }}
selectRow={selectRow}>
<TableHeaderColumn dataField='id' isKey={true}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name' expandable={false}>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price' expandable={false}>Product Price</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Table mouse enter/leave events
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/others/mouse-event-table.js
*/
class MouseEventTable extends React.Component {
render() {
const options: Options<Product> = {
onMouseLeave: () => { console.log('mouse left table'); },
onMouseEnter: () => { console.log('mouse entered table'); },
onRowMouseOut: (row: any, e: React.MouseEvent<{}>) => {
console.log(e);
console.log('mouse left row ' + row.id);
},
onRowMouseOver: (row: any, e: React.MouseEvent<{}>) => {
console.log(e);
console.log('mouse entered row ' + row.id);
}
};
return (
<BootstrapTable data={products} options={options}>
<TableHeaderColumn dataField='id' isKey={true}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Hidden on insert modal with async row error callback & read-only field
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/advance/hide-on-insert-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/advance/insert-error-handle-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/advance/validator-table-read-only.js
*/
class HideOnInsertTable extends React.Component {
handleAddRowWithASyncError = (row: any, colInfo: ReadonlyArray<ColumnDescription<Job>>, errorCallback: (msg: string) => void) => {
setTimeout(() => {
errorCallback('Sorry, There\'s some error happend');
}, 5000);
return false;
}
render() {
const options: Options<Job> = {
onAddRow: this.handleAddRowWithASyncError
};
return (
<BootstrapTable data={jobs} insertRow={true} options={options}>
<TableHeaderColumn dataField='id' isKey={true} autoValue>Job ID</TableHeaderColumn>
<TableHeaderColumn dataField='name' hiddenOnInsert>Job Name</TableHeaderColumn>
<TableHeaderColumn dataField='type' editable={{ type: 'select', options: { values: jobTypes }, readOnly: true }}>Job Type</TableHeaderColumn>
<TableHeaderColumn dataField='active' editable={{ type: 'checkbox', options: { values: 'Y:N' } }}>Active</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Edit field types
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/advance/edit-type-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/advance/insert-default-value-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/advance/insert-error-handle-table.js
*/
class EditTypeTable extends React.Component {
formatType = (cell: string) => `TYPE_${cell}`;
jobTypes = (row: ExtendedJob) => (row.id > 2) ? ['A', 'B'] : ['B', 'C', 'D', 'E'];
handleAddRowWithSyncError = () => {
return 'Sorry, There\'s some error happend';
}
render() {
const attrs = {
rows: 10,
onKeyDown: () => { console.log('keydown event trigger'); }
};
const cellEditProp: CellEdit<ExtendedJob> = {
mode: 'click',
blurToSave: true
};
const options: Options<ExtendedJob> = {
onAddRow: this.handleAddRowWithSyncError
};
return (
<BootstrapTable data={extendedJobs} cellEdit={cellEditProp} options={options} insertRow={true}>
<TableHeaderColumn dataField='id' isKey={true}>Job ID</TableHeaderColumn>
<TableHeaderColumn dataField='name' editable={{ type: 'textarea', attrs, defaultValue: 'Default Job Name' }}>Job Name</TableHeaderColumn>
<TableHeaderColumn dataField='type1' dataFormat={this.formatType} editable={{ type: 'select', options: { values: jobTypes }, defaultValue: 'C' }}>Job Type1</TableHeaderColumn>
<TableHeaderColumn dataField='type2' editable={{ type: 'select', options: { values: this.jobTypes }, defaultValue: 'A' }}>Job Type2</TableHeaderColumn>
<TableHeaderColumn dataField='active' editable={{ type: 'checkbox', options: { values: 'Y:N' }, defaultValue: 'N' }}>Active</TableHeaderColumn>
<TableHeaderColumn dataField='datetime' editable={{ type: 'datetime', defaultValue: new Date() }}>Date Time</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* React component format for column.
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/column-format/react-column-format-table.js
*/
class ActiveFormatter extends React.Component<{ active: boolean }> {
render() {
return (
<input type='checkbox' checked={this.props.active} />
);
}
}
export default class ReactColumnFormatTable extends React.Component {
activeFormatter = (cell: boolean, row: ExtendedJob) => (<ActiveFormatter active={cell} />);
render() {
return (
<BootstrapTable data={extendedJobs}>
<TableHeaderColumn dataField='id' isKey={true} hidden={true}>Job ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Job Name</TableHeaderColumn>
<TableHeaderColumn dataField='active' dataFormat={this.activeFormatter}>Active</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Format Extra Data
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/column-format/extra-data-column-format-table.js
*/
class ExtraDataColumnFormatTable extends React.Component {
enumFormatter = (cell: number, row: Product, enumObject: {[id: number]: string}) => enumObject[cell];
render() {
return (
<BootstrapTable data={products} >
<TableHeaderColumn dataField='id' isKey={true} dataAlign='center'>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name' headerAlign='center' dataAlign='right'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='quality' dataFormat={enumFormatter} formatExtraData={qualityType}>Product Quality</TableHeaderColumn>
<TableHeaderColumn dataField='inStock' dataFormat={enumFormatter} formatExtraData={inStockStatus}>Product Stock Status</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Column titles
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/column/column-title-table.js
*/
class ColumnAlignTable extends React.Component {
customTitle = (cell: number, row: any, rowIndex: number, colIndex: number) => `${row.name} for ${cell}`;
render() {
const options: Options<Product> = {
exportCSVText: 'my_export',
insertText: 'my_insert',
deleteText: 'my_delete',
saveText: 'my_save',
closeText: 'my_close'
};
return (
<BootstrapTable data={products} options={options}>
<TableHeaderColumn dataField='id' isKey={true} columnTitle={this.customTitle} >Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name' width='50%' headerTitle={false} columnTitle={true}>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price' columnTitle='Hard code string' headerText='Custom Title'>Product Price</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Table Footer
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/footer/footer-table.js
*/
class FooterTable extends React.Component {
render() {
const footerData: FooterData[][] = [
[
{ label: 'Total', columnIndex: 0 },
{
label: 'Total value',
columnIndex: 2,
align: 'right',
formatter: (tableData: Array<{price: number}>) => {
let label = 0;
for (let i = 0, tableDataLen = tableData.length; i < tableDataLen; i++) {
label += tableData[i].price;
}
return (
<strong>{label}</strong>
);
}
}
]
];
return (
<div>
<BootstrapTable data={products} footerData={footerData} footer pagination search keyBoardNav>
<TableHeaderColumn dataField='id' isKey={true}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>
</div>
);
}
}
/**
* Keyboard navigation
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/keyboard-nav/custom-style-nav-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/keyboard-nav/custom-style-nav-with-cell-edit-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/keyboard-nav/disable-click-to-nav-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/keyboard-nav/enter-to-edit-with-nav-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/keyboard-nav/nav-with-expand-table.js
*/
class CustomStyleNavTable extends React.Component {
customStyle = (cell: any, row: any) => {
return {
backgroundColor: 'red'
};
}
render() {
const cellEdit: CellEdit<Product> = {
mode: 'click',
blurToSave: true
};
const keyBoardNav = {
customStyleOnEditCell: this.customStyle,
customStyle: this.customStyle,
clickToNav: false,
enterToEdit: true,
enterToExpand: false
};
return (
<BootstrapTable data={products} keyBoardNav={keyBoardNav} cellEdit={cellEdit}>
<TableHeaderColumn dataField='id' isKey={true}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Table body styles
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/style/inline-style-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/style/table-class-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/style/td-class-string-table.js
*/
class TrClassStringTable extends React.Component {
render() {
return (
<BootstrapTable insertRow exportCSV data={products}
tableStyle={{ border: '#0000FF 2.5px solid' }}
containerStyle={{ border: '#FFBB73 2.5px solid' }}
headerStyle={{ border: 'red 1px solid' }}
bodyStyle={{ border: 'green 1px solid' }}
tableHeaderClass='my-header-class'
tableBodyClass='my-body-class'
containerClass='my-container-class'
tableContainerClass='my-table-container-class'
headerContainerClass='my-header-container-class'
bodyContainerClass='my-body-container-class'
trClassName='tr-string-example'>
<TableHeaderColumn dataField='id' isKey={true}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name' columnClassName='td-column-string-example'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price' className='td-header-string-example'>Product Price</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Table styles set by functions.
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/style/td-class-function-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/style/tr-class-function-table.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/style/tr-style-table.js
*/
class TrClassFunctionTable extends React.Component {
headerColumnClassNameFormat = () => 'th-string-example';
columnClassNameFormat = (fieldValue: string | number, row: Product, rowIdx: number, colIdx: number) =>
rowIdx % 2 === 0 ? 'td-column-function-even-example' : 'td-column-function-odd-example'
trClassFormat = (rowData: ReadonlyArray<Product>, rIndex: number) =>
rIndex % 3 === 0 ? 'tr-function-example' : ''
trStyle = (row: Product, rowIndex: number) => ({ backgroundColor: '#FFFAFA' });
render() {
return (
<BootstrapTable data={products} trClassName={this.trClassFormat} trStyle={this.trStyle} >
<TableHeaderColumn dataField='id' isKey={true}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name' className={this.headerColumnClassNameFormat}>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price' columnClassName={this.columnClassNameFormat}>Product Price</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Filter types.
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/column-filter/all-filters.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/column-filter/date-filter-programmatically.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/column-filter/number-filter-programmatically.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/column-filter/regex-filter-programmatically.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/column-filter/select-filter-programmatically.js
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/column-filter/text-filter-programmatically.js
*/
class AllFilters extends React.Component {
name1: TableHeaderColumn | null;
name2: TableHeaderColumn | null;
quality: TableHeaderColumn | null;
price: TableHeaderColumn | null;
satisfaction: TableHeaderColumn | null;
inStockDate: TableHeaderColumn | null;
handlerClickCleanFiltered = () => {
this.name1.cleanFiltered();
this.name2.cleanFiltered();
this.quality.cleanFiltered();
this.price.cleanFiltered();
this.satisfaction.cleanFiltered();
this.inStockDate.cleanFiltered();
}
applyFiltersProgramatically = () => {
this.name1.applyFilter('Item 1');
this.name2.applyFilter('[name]');
this.quality.applyFilter(1);
this.price.applyFilter({
number: 10.5,
comparator: '<='
});
this.satisfaction.applyFilter({
number: 2,
comparator: '>'
});
this.inStockDate.applyFilter({
date: new Date(2015, 0, 1),
comparator: '='
});
}
dateFormatter = (cell: Date, row: any) => {
if (typeof cell !== 'object') {
cell = new Date(cell);
}
return `${('0' + cell.getDate()).slice(-2)}/${('0' + (cell.getMonth() + 1)).slice(-2)}/${cell.getFullYear()}`;
}
render() {
const satisfaction = [0, 1, 2, 3, 4, 5];
return (
<BootstrapTable ref='table' data={products}>
<TableHeaderColumn dataField='id' isKey={true}>
Product ID
<br /><a onClick={this.handlerClickCleanFiltered} style={{ cursor: 'pointer' }}>clear filters</a>
</TableHeaderColumn>
<TableHeaderColumn ref={(node) => { this.name1 = node; }} dataField='name' filter={{ type: 'TextFilter', placeholder: 'Please enter a value' }}>Product Name</TableHeaderColumn>
<TableHeaderColumn ref={(node) => { this.name2 = node; }} dataField='name' filter={{ type: 'RegexFilter', placeholder: 'Please enter a regex' }}>Product Name</TableHeaderColumn>
< TableHeaderColumn ref={(node) => { this.quality = node; }} dataField='quality' filter={{ type: 'SelectFilter', options: qualityType }}
dataFormat={enumFormatter} formatExtraData={qualityType}>Product Quality</TableHeaderColumn>
<TableHeaderColumn ref={(node) => { this.price = node; }} dataField='price' filter={{ type: 'NumberFilter', delay: 1000 }}>Product Price</TableHeaderColumn>
< TableHeaderColumn ref= {(node) => { this.satisfaction = node; }} dataField='satisfaction' filter={{ type: 'NumberFilter', options: satisfaction }}>Buyer Satisfaction</TableHeaderColumn>
< TableHeaderColumn ref= {(node) => { this.inStockDate = node; }} dataField='inStockDate' filter={{ type: 'DateFilter' }} dataFormat={this.dateFormatter}>In Stock From</TableHeaderColumn>
</BootstrapTable>
);
}
}
/**
* Set Array filter programatically
* @see https://github.com/AllenFang/react-bootstrap-table/blob/master/examples/js/column-filter/array-filter-programmatically.js
*/
class ProgrammaticallyArrayFilter extends React.Component {
table: BootstrapTable | null;
/* Filtering passing an array of values */
handleBtnClick = () => {
this.table.handleFilterData({
name: { type: 'ArrayFilter', value: ['Item name 3', 'Item name 4'] },
price: { type: 'ArrayFilter', value: [2100, 2104] }
});
}
render() {
return (
<div>
<button onClick={this.handleBtnClick} className='btn btn-default'>Click to apply text filter</button>
<BootstrapTable ref={(node) => { this.table = node; }} data={products}>
<TableHeaderColumn dataField='id' isKey={true}>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name' filter={{ type: 'TextFilter', delay: 1000 }}>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>
</div>
);
}
}