Skip to content
This repository was archived by the owner on Jan 15, 2022. It is now read-only.

Commit 1eb6eb9

Browse files
committed
Allow specifying table rows in custom components
Use the structure returned by `react.createElement` to do a render of any child components with unrecognized types, and extract the data out of them if they themselves return a `<Tr>`
1 parent d19826d commit 1eb6eb9

5 files changed

Lines changed: 118 additions & 18 deletions

File tree

build/reactable.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,17 +1046,27 @@ window.React["default"] = window.React;
10461046
return;
10471047
}
10481048

1049-
switch (child.type) {
1049+
var reactableDescendant = undefined;
1050+
var test = undefined;
1051+
1052+
if ([_tfoot.Tfoot, _thead.Thead, _tr.Tr].indexOf(child.type) >= 0) {
1053+
reactableDescendant = child;
1054+
} else {
1055+
reactableDescendant = new child.type(child.props).render();
1056+
test = true;
1057+
}
1058+
1059+
switch (reactableDescendant.type) {
10501060
case _tfoot.Tfoot:
10511061
if (typeof tfoot !== 'undefined') {
10521062
console.warn('You can only have one <Tfoot>, but more than one was specified.' + 'Ignoring all but the last one');
10531063
}
10541064
tfoot = child;
10551065
break;
10561066
case _tr.Tr:
1057-
var childData = child.props.data || {};
1067+
var childData = reactableDescendant.props.data || {};
10581068

1059-
_react['default'].Children.forEach(child.props.children, function (descendant) {
1069+
_react['default'].Children.forEach(reactableDescendant.props.children, function (descendant) {
10601070
// TODO
10611071
/* if (descendant.type.ConvenienceConstructor === Td) { */
10621072
if (typeof descendant !== 'object' || descendant == null) {
@@ -1069,7 +1079,7 @@ window.React["default"] = window.React;
10691079
} else if (typeof descendant.props.children !== 'undefined') {
10701080
value = descendant.props.children;
10711081
} else {
1072-
console.warn('exports.Td specified without ' + 'a `data` property or children, ' + 'ignoring');
1082+
console.warn('Td specified without ' + 'a `data` property or children, ' + 'ignoring');
10731083
return;
10741084
}
10751085

@@ -1085,7 +1095,7 @@ window.React["default"] = window.React;
10851095

10861096
data.push({
10871097
data: childData,
1088-
props: (0, _libFilter_props_from.filterPropsFrom)(child.props),
1098+
props: (0, _libFilter_props_from.filterPropsFrom)(reactableDescendant.props),
10891099
__reactableMeta: true
10901100
});
10911101
break;

build/tests/reactable_test.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,75 @@
610610
});
611611
});
612612

613+
describe('adding <CustomComponents>s to the <Table>', function () {
614+
before(function () {
615+
var CustomComponent = React.createClass({
616+
displayName: "CustomComponent",
617+
propTypes: {
618+
name: React.PropTypes.string,
619+
age: React.PropTypes.number,
620+
position: React.PropTypes.string
621+
},
622+
render: function render() {
623+
return React.createElement(
624+
Reactable.Tr,
625+
null,
626+
React.createElement(
627+
Reactable.Td,
628+
{ column: 'Name' },
629+
this.props.name || ''
630+
),
631+
React.createElement(
632+
Reactable.Td,
633+
{ column: 'Age' },
634+
this.props.age || ''
635+
),
636+
React.createElement(
637+
Reactable.Td,
638+
{ column: 'Position' },
639+
this.props.position || ''
640+
)
641+
);
642+
}
643+
});
644+
645+
React.render(React.createElement(
646+
Reactable.Table,
647+
{ className: 'table', id: 'table' },
648+
React.createElement(CustomComponent, { name: 'Griffin Smith', age: 18 }),
649+
React.createElement(CustomComponent, { name: 'Lee Salminen', age: 23 }),
650+
React.createElement(CustomComponent, { age: 28, position: 'Developer' })
651+
), ReactableTestUtils.testNode());
652+
});
653+
654+
after(ReactableTestUtils.resetTestEnvironment);
655+
656+
it('renders the table', function () {
657+
expect($('table#table.table')).to.exist;
658+
});
659+
660+
it('renders the column headers in the table', function () {
661+
var headers = [];
662+
$('thead th').each(function () {
663+
headers.push($(this).text());
664+
});
665+
666+
expect(headers).to.eql(['Name', 'Age', 'Position']);
667+
});
668+
669+
it('renders the first row with the correct data', function () {
670+
ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']);
671+
});
672+
673+
it('renders the second row with the correct data', function () {
674+
ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']);
675+
});
676+
677+
it('renders the third row with the correct data', function () {
678+
ReactableTestUtils.expectRowText(2, ['', '28', 'Developer']);
679+
});
680+
});
681+
613682
describe('passing through HTML props', function () {
614683
describe('adding <Tr>s with className to the <Table>', function () {
615684
before(function () {

lib/reactable/table.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,17 +100,27 @@ var Table = (function (_React$Component) {
100100
return;
101101
}
102102

103-
switch (child.type) {
103+
var reactableDescendant = undefined;
104+
var test = undefined;
105+
106+
if ([_tfoot.Tfoot, _thead.Thead, _tr.Tr].indexOf(child.type) >= 0) {
107+
reactableDescendant = child;
108+
} else {
109+
reactableDescendant = new child.type(child.props).render();
110+
test = true;
111+
}
112+
113+
switch (reactableDescendant.type) {
104114
case _tfoot.Tfoot:
105115
if (typeof tfoot !== 'undefined') {
106116
console.warn('You can only have one <Tfoot>, but more than one was specified.' + 'Ignoring all but the last one');
107117
}
108118
tfoot = child;
109119
break;
110120
case _tr.Tr:
111-
var childData = child.props.data || {};
121+
var childData = reactableDescendant.props.data || {};
112122

113-
_react2['default'].Children.forEach(child.props.children, function (descendant) {
123+
_react2['default'].Children.forEach(reactableDescendant.props.children, function (descendant) {
114124
// TODO
115125
/* if (descendant.type.ConvenienceConstructor === Td) { */
116126
if (typeof descendant !== 'object' || descendant == null) {
@@ -123,7 +133,7 @@ var Table = (function (_React$Component) {
123133
} else if (typeof descendant.props.children !== 'undefined') {
124134
value = descendant.props.children;
125135
} else {
126-
console.warn('exports.Td specified without ' + 'a `data` property or children, ' + 'ignoring');
136+
console.warn('Td specified without ' + 'a `data` property or children, ' + 'ignoring');
127137
return;
128138
}
129139

@@ -139,7 +149,7 @@ var Table = (function (_React$Component) {
139149

140150
data.push({
141151
data: childData,
142-
props: (0, _libFilter_props_from.filterPropsFrom)(child.props),
152+
props: (0, _libFilter_props_from.filterPropsFrom)(reactableDescendant.props),
143153
__reactableMeta: true
144154
});
145155
break;

src/reactable/table.jsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,17 @@ export class Table extends React.Component {
6262
return;
6363
}
6464

65-
switch (child.type) {
65+
let reactableDescendant;
66+
let test;
67+
68+
if ([Tfoot, Thead, Tr].indexOf(child.type) >= 0) {
69+
reactableDescendant = child
70+
} else {
71+
reactableDescendant = (new child.type(child.props)).render()
72+
test = true
73+
}
74+
75+
switch (reactableDescendant.type) {
6676
case Tfoot:
6777
if (typeof(tfoot) !== 'undefined') {
6878
console.warn ('You can only have one <Tfoot>, but more than one was specified.' +
@@ -71,9 +81,9 @@ export class Table extends React.Component {
7181
tfoot = child;
7282
break;
7383
case Tr:
74-
let childData = child.props.data || {};
84+
let childData = reactableDescendant.props.data || {};
7585

76-
React.Children.forEach(child.props.children, function(descendant) {
86+
React.Children.forEach(reactableDescendant.props.children, function(descendant) {
7787
// TODO
7888
/* if (descendant.type.ConvenienceConstructor === Td) { */
7989
if (
@@ -89,7 +99,7 @@ export class Table extends React.Component {
8999
} else if (typeof(descendant.props.children) !== 'undefined') {
90100
value = descendant.props.children;
91101
} else {
92-
console.warn('exports.Td specified without ' +
102+
console.warn('Td specified without ' +
93103
'a `data` property or children, ' +
94104
'ignoring');
95105
return;
@@ -108,7 +118,7 @@ export class Table extends React.Component {
108118

109119
data.push({
110120
data: childData,
111-
props: filterPropsFrom(child.props),
121+
props: filterPropsFrom(reactableDescendant.props),
112122
__reactableMeta: true
113123
});
114124
break;

tests/reactable_test.jsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -429,13 +429,14 @@ describe('Reactable', function() {
429429
render: function(){
430430
return (
431431
<Reactable.Tr>
432-
<Reactable.Td column="Name">{this.props.name}</Reactable.Td>
433-
<Reactable.Td column="Age">{this.props.age}</Reactable.Td>
434-
<Reactable.Td column="Position">{this.props.position}</Reactable.Td>
432+
<Reactable.Td column="Name">{this.props.name || ''}</Reactable.Td>
433+
<Reactable.Td column="Age">{this.props.age || ''}</Reactable.Td>
434+
<Reactable.Td column="Position">{this.props.position || ''}</Reactable.Td>
435435
</Reactable.Tr>
436436
);
437437
}
438438
});
439+
439440
React.render(
440441
<Reactable.Table className="table" id="table">
441442
<CustomComponent name='Griffin Smith' age={18} />

0 commit comments

Comments
 (0)