Hey, thanks for all your work on react-toolbox. We are trying out the css-next branch and really enjoying it. One issue that were having with the new table is wrapping TableRow in another component to be rendered in a table. E.g.
<Table selectable={false}>
<TableHead>
<TableCell>Widget</TableCell>
<TableCell>Price</TableCell>
<TableCell>Color</TableCell>
</TableHead>
{ this.props.wigets.map((widget, i) => (
<WidgetRow key={i} widget={widget} />
))}
</Table>
Where WidgetRow renders something like:
<TableRow>
<TableCell>{this.props.widget.name}</TableCell>
<TableCell>
<Input
type="text"
value={this.state.price}
onChange={this.handlePriceChange}
onBlur={this.savePriceChange}
/>
</TableCell>
<TableCell>
<Input
type="text"
value={this.state.color}
onChange={this.handleColorChange}
onBlur={this.saveColorChange}
/>
</TableCell>
</TableRow>
We thought it would be good to extract table rows into their own component so that we wouldn't have to maintain a multi-dimensional array of states for each widget/attribute. Is this a use-case you would like to support for the new react-toolbox tables? Is there another prefered method to accomplish this? Would you be open to a pull request to allow for components to wrap TableRow in a Table?.
The most interesting way to solve this is by using dependency injection. If you look at the code here you will see there is a factory function exposed to build the Table component. This means you can manually invoke this factory injecting your custom component. For example:
// CustomTable.js
import { themr } from 'react-css-themr';
import { TABLE } from 'react-toolbox/lib/identifiers';
import { factory as tableFactory } from 'react-toolbox/lib/table/Table';
import { TableRow, TableHead } from 'react-toolbox/lib/table';
// Define your custom row
const CustomRow = props => <TableRow {...props} />;
// Create a new Table component injecting Head and Row
// Feel free to inject default styles there, check index.js
const Table = themr(TABLE)(tableFactory(TableHead, CustomRow));
export default Table;
export { TableHead };
export { CustomRow as TableRow };
Another (way more straightforward alternative) would be to add two properties to the Table component accepting TableHead and TableRow but I prefer this one because it clearly separates component dependencies from props.
I did this and still not rendering.
Doing some debug
function defaultChecker(classType, reactElement) {
console.log(reactElement.type === classType);
console.log(classType);
console.log(reactElement.type);
return reactElement && reactElement.type === classType;
}
My code
import React from 'react';
import { themr } from 'react-css-themr';
import { TABLE } from 'react-toolbox/lib/identifiers';
import { tableFactory } from 'react-toolbox/lib/table/Table';
import { TableHead, TableCell } from 'react-toolbox/lib/table';
import TableRow from './ListItem';
const Table = themr(TABLE)(tableFactory(TableHead, TableRow));
const CategoryList = ({ categories, onActiveStatusChanged }) => (
<Table selectable={false} >
<TableHead>
<TableCell>Nombre</TableCell>
<TableCell>Slug</TableCell>
<TableCell>Está activo</TableCell>
</TableHead>
{categories.map(item => (
<TableRow
category={item}
onActiveStatusChanged={onActiveStatusChanged}
key={item._id}
/>
))}
</Table>
);
CategoryList.propTypes = {
categories: React.PropTypes.arrayOf(React.PropTypes.shape({
name: React.PropTypes.string.isRequired,
slug: React.PropTypes.string.isRequired,
is_active: React.PropTypes.bool,
})).isRequired,
onActiveStatusChanged: React.PropTypes.func.isRequired,
};
CategoryList.defaultProps = {
};
export default CategoryList;
The console output is:
false
is-component-of-type.js:28 function ListItem() {
var _ref;
var _temp, _this, _ret;
_classCallCheck(this, ListItem);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
…
is-component-of-type.js:29 function ListItem() {
var _ref;
var _temp, _this, _ret;
_classCallCheck(this, ListItem);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
…
Most helpful comment
The most interesting way to solve this is by using dependency injection. If you look at the code here you will see there is a
factoryfunction exposed to build theTablecomponent. This means you can manually invoke this factory injecting your custom component. For example:Another (way more straightforward alternative) would be to add two properties to the
Tablecomponent acceptingTableHeadandTableRowbut I prefer this one because it clearly separates component dependencies from props.