Skip to content

Instantly share code, notes, and snippets.

@zwily
Last active August 29, 2015 14:03
Show Gist options
  • Save zwily/6cf776c362ef28ad8852 to your computer and use it in GitHub Desktop.
Save zwily/6cf776c362ef28ad8852 to your computer and use it in GitHub Desktop.
simple sortable table react component
/** @jsx React.DOM */
var React = require('react'),
types = React.PropTypes,
_ = require('underscore');
module.exports = React.createClass({
propTypes: {
columns: types.arrayOf(
types.shape({
name: types.string.isRequired,
displayName: types.string,
formatter: types.func,
disableSort: types.bool
})
),
rows: types.arrayOf(types.object),
defaultColumn: types.string,
defaultDirection: types.oneOf(['asc', 'desc'])
},
getInitialState: function() {
return {
currentColumn: this.props.defaultColumn || this.props.columns[0].name,
currentDirection: this.props.defaultDirection || 'asc',
sortBy: null
}
},
handleHeaderClick: function(column) {
return function(event) {
if (this.state.currentColumn == column.name) {
this.setState({
currentDirection: this.state.currentDirection == 'asc' ? 'desc' : 'asc'
});
}
else {
this.setState({
currentColumn: column.name,
currentDirection: 'asc'
});
}
}.bind(this);
},
renderHeaderRow: function() {
var headers = [];
for (var i = 0; i < this.props.columns.length; i++) {
var columnInfo = this.props.columns[i];
var arrow = null;
if (this.state.currentColumn == columnInfo.name) {
if (this.state.currentDirection == 'asc') {
arrow = <span>&#9650;</span>;
}
else {
arrow = <span>&#9660;</span>;
}
}
var onclick = null;
if (!columnInfo.disableSort) {
onclick = this.handleHeaderClick(columnInfo);
}
headers.push(
<th onClick={onclick} key={columnInfo.name}>
{arrow} {columnInfo.displayName || columnInfo.name}
</th>
);
}
return <tr>{headers}</tr>;
},
renderRows: function() {
var sortedData = _.sortBy(this.props.rows, this.state.currentColumn);
if (this.state.currentDirection != 'asc') {
sortedData.reverse();
}
var rows = _.map(sortedData, function(rowData) {
var tds = _.map(this.props.columns, function(columnInfo) {
var value = rowData[columnInfo.name];
if (columnInfo.formatter) {
value = columnInfo.formatter(value);
}
return <td>{value}</td>;
}, this);
return <tr>{tds}</tr>;
}, this);
return rows;
},
render: function() {
return (
<table className={this.props.className}>
<tbody>
{this.renderHeaderRow()}
{this.renderRows()}
</tbody>
</table>
);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment