diff --git a/build/reactable.js b/build/reactable.js index 463dc9cc..c298e1d4 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -1046,7 +1046,17 @@ window.React["default"] = window.React; return; } - switch (child.type) { + var reactableDescendant = undefined; + var test = undefined; + + if ([_tfoot.Tfoot, _thead.Thead, _tr.Tr].indexOf(child.type) >= 0) { + reactableDescendant = child; + } else { + reactableDescendant = new child.type(child.props, child._context).render(); + test = true; + } + + switch (reactableDescendant.type) { case _tfoot.Tfoot: if (typeof tfoot !== 'undefined') { console.warn('You can only have one , but more than one was specified.' + 'Ignoring all but the last one'); @@ -1054,9 +1064,9 @@ window.React["default"] = window.React; tfoot = child; break; case _tr.Tr: - var childData = child.props.data || {}; + var childData = reactableDescendant.props.data || {}; - _react['default'].Children.forEach(child.props.children, function (descendant) { + _react['default'].Children.forEach(reactableDescendant.props.children, function (descendant) { // TODO /* if (descendant.type.ConvenienceConstructor === Td) { */ if (typeof descendant !== 'object' || descendant == null) { @@ -1069,7 +1079,7 @@ window.React["default"] = window.React; } else if (typeof descendant.props.children !== 'undefined') { value = descendant.props.children; } else { - console.warn('exports.Td specified without ' + 'a `data` property or children, ' + 'ignoring'); + console.warn('Td specified without ' + 'a `data` property or children, ' + 'ignoring'); return; } @@ -1085,7 +1095,7 @@ window.React["default"] = window.React; data.push({ data: childData, - props: (0, _libFilter_props_from.filterPropsFrom)(child.props), + props: (0, _libFilter_props_from.filterPropsFrom)(reactableDescendant.props), __reactableMeta: true }); break; diff --git a/build/tests/reactable_test.js b/build/tests/reactable_test.js index 6bf0bfb9..b9aa180b 100644 --- a/build/tests/reactable_test.js +++ b/build/tests/reactable_test.js @@ -610,6 +610,134 @@ }); }); + describe('adding s to the ', function () { + context('passing through props', function () { + before(function () { + var CustomComponent = React.createClass({ + displayName: "CustomComponent", + propTypes: { + name: React.PropTypes.string, + age: React.PropTypes.number, + position: React.PropTypes.string + }, + render: function render() { + return React.createElement( + Reactable.Tr, + null, + React.createElement( + Reactable.Td, + { column: 'Name' }, + this.props.name || '' + ), + React.createElement( + Reactable.Td, + { column: 'Age' }, + this.props.age || '' + ), + React.createElement( + Reactable.Td, + { column: 'Position' }, + this.props.position || '' + ) + ); + } + }); + + React.render(React.createElement( + Reactable.Table, + { className: 'table', id: 'table' }, + React.createElement(CustomComponent, { name: 'Griffin Smith', age: 18 }), + React.createElement(CustomComponent, { name: 'Lee Salminen', age: 23 }), + React.createElement(CustomComponent, { age: 28, position: 'Developer' }) + ), ReactableTestUtils.testNode()); + }); + + after(ReactableTestUtils.resetTestEnvironment); + + it('renders the table', function () { + expect($('table#table.table')).to.exist; + }); + + it('renders the column headers in the table', function () { + var headers = []; + $('thead th').each(function () { + headers.push($(this).text()); + }); + + expect(headers).to.eql(['Name', 'Age', 'Position']); + }); + + it('renders the first row with the correct data', function () { + ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']); + }); + + it('renders the second row with the correct data', function () { + ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']); + }); + + it('renders the third row with the correct data', function () { + ReactableTestUtils.expectRowText(2, ['', '28', 'Developer']); + }); + }); + + context('passing through context', function () { + before(function () { + var RowComponent = React.createClass({ + displayName: 'CustomComponent', + contextTypes: { test: React.PropTypes.string }, + render: function render() { + return React.createElement( + Reactable.Tr, + null, + React.createElement( + Reactable.Td, + { column: 'Name' }, + this.props.name || '' + ), + React.createElement( + Reactable.Td, + { column: 'Test' }, + this.context.test || '' + ) + ); + } + }); + + var TableComponent = React.createClass({ + displayName: 'TableComponent', + childContextTypes: { test: React.PropTypes.string }, + getChildContext: function getChildContext() { + return { test: 'foobar' }; + }, + render: function render() { + return React.createElement( + Reactable.Table, + { className: 'table', id: 'table' }, + React.createElement(RowComponent, { name: 'Griffin Smith' }), + React.createElement(RowComponent, { name: 'Lee Salminen' }) + ); + } + }); + + React.render(React.createElement(TableComponent, null), ReactableTestUtils.testNode()); + }); + + after(ReactableTestUtils.resetTestEnvironment); + + it('renders the table', function () { + expect($('table#table.table')).to.exist; + }); + + it('renders the first row with the correct data', function () { + ReactableTestUtils.expectRowText(0, ['Griffin Smith', 'foobar']); + }); + + it('renders the second row with the correct data', function () { + ReactableTestUtils.expectRowText(1, ['Lee Salminen', 'foobar']); + }); + }); + }); + describe('passing through HTML props', function () { describe('adding s with className to the
', function () { before(function () { diff --git a/lib/reactable/table.js b/lib/reactable/table.js index 24f036c5..6e07569e 100644 --- a/lib/reactable/table.js +++ b/lib/reactable/table.js @@ -100,7 +100,17 @@ var Table = (function (_React$Component) { return; } - switch (child.type) { + var reactableDescendant = undefined; + var test = undefined; + + if ([_tfoot.Tfoot, _thead.Thead, _tr.Tr].indexOf(child.type) >= 0) { + reactableDescendant = child; + } else { + reactableDescendant = new child.type(child.props, child._context).render(); + test = true; + } + + switch (reactableDescendant.type) { case _tfoot.Tfoot: if (typeof tfoot !== 'undefined') { console.warn('You can only have one , but more than one was specified.' + 'Ignoring all but the last one'); @@ -108,9 +118,9 @@ var Table = (function (_React$Component) { tfoot = child; break; case _tr.Tr: - var childData = child.props.data || {}; + var childData = reactableDescendant.props.data || {}; - _react2['default'].Children.forEach(child.props.children, function (descendant) { + _react2['default'].Children.forEach(reactableDescendant.props.children, function (descendant) { // TODO /* if (descendant.type.ConvenienceConstructor === Td) { */ if (typeof descendant !== 'object' || descendant == null) { @@ -123,7 +133,7 @@ var Table = (function (_React$Component) { } else if (typeof descendant.props.children !== 'undefined') { value = descendant.props.children; } else { - console.warn('exports.Td specified without ' + 'a `data` property or children, ' + 'ignoring'); + console.warn('Td specified without ' + 'a `data` property or children, ' + 'ignoring'); return; } @@ -139,7 +149,7 @@ var Table = (function (_React$Component) { data.push({ data: childData, - props: (0, _libFilter_props_from.filterPropsFrom)(child.props), + props: (0, _libFilter_props_from.filterPropsFrom)(reactableDescendant.props), __reactableMeta: true }); break; diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index e69f1bd3..eb67dd60 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -62,7 +62,17 @@ export class Table extends React.Component { return; } - switch (child.type) { + let reactableDescendant; + let test; + + if ([Tfoot, Thead, Tr].indexOf(child.type) >= 0) { + reactableDescendant = child + } else { + reactableDescendant = (new child.type(child.props, child._context)).render() + test = true + } + + switch (reactableDescendant.type) { case Tfoot: if (typeof(tfoot) !== 'undefined') { console.warn ('You can only have one , but more than one was specified.' + @@ -71,9 +81,9 @@ export class Table extends React.Component { tfoot = child; break; case Tr: - let childData = child.props.data || {}; + let childData = reactableDescendant.props.data || {}; - React.Children.forEach(child.props.children, function(descendant) { + React.Children.forEach(reactableDescendant.props.children, function(descendant) { // TODO /* if (descendant.type.ConvenienceConstructor === Td) { */ if ( @@ -89,7 +99,7 @@ export class Table extends React.Component { } else if (typeof(descendant.props.children) !== 'undefined') { value = descendant.props.children; } else { - console.warn('exports.Td specified without ' + + console.warn('Td specified without ' + 'a `data` property or children, ' + 'ignoring'); return; @@ -108,7 +118,7 @@ export class Table extends React.Component { data.push({ data: childData, - props: filterPropsFrom(child.props), + props: filterPropsFrom(reactableDescendant.props), __reactableMeta: true }); break; diff --git a/tests/reactable_test.jsx b/tests/reactable_test.jsx index b2232dc6..65ee8b86 100644 --- a/tests/reactable_test.jsx +++ b/tests/reactable_test.jsx @@ -417,6 +417,115 @@ describe('Reactable', function() { }); }); + describe('adding s to the
', function() { + context('passing through props', function() { + before(function() { + var CustomComponent = React.createClass({ + displayName: "CustomComponent", + propTypes:{ + name: React.PropTypes.string, + age: React.PropTypes.number, + position: React.PropTypes.string + }, + render: function(){ + return ( + + {this.props.name || ''} + {this.props.age || ''} + {this.props.position || ''} + + ); + } + }); + + React.render( + + + + + , + ReactableTestUtils.testNode() + ); + }); + + after(ReactableTestUtils.resetTestEnvironment); + + it('renders the table', function() { + expect($('table#table.table')).to.exist; + }); + + it('renders the column headers in the table', function() { + var headers = []; + $('thead th').each(function() { + headers.push($(this).text()); + }); + + expect(headers).to.eql([ 'Name', 'Age', 'Position' ]); + }); + + it('renders the first row with the correct data', function() { + ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']); + }); + + it('renders the second row with the correct data', function() { + ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']); + }); + + it('renders the third row with the correct data', function() { + ReactableTestUtils.expectRowText(2, ['', '28', 'Developer']); + }); + }); + + context('passing through context', function() { + before(function() { + let RowComponent = React.createClass({ + displayName: 'CustomComponent', + contextTypes: { test: React.PropTypes.string }, + render: function(){ + return ( + + {this.props.name || ''} + {this.context.test || ''} + + ); + } + }); + + let TableComponent = React.createClass({ + displayName: 'TableComponent', + childContextTypes: { test: React.PropTypes.string }, + getChildContext: function() { + return { test: 'foobar' }; + }, + render: function() { + return ( + + + + + ); + } + }); + + React.render(, ReactableTestUtils.testNode()); + }); + + after(ReactableTestUtils.resetTestEnvironment); + + it('renders the table', function() { + expect($('table#table.table')).to.exist; + }); + + it('renders the first row with the correct data', function() { + ReactableTestUtils.expectRowText(0, ['Griffin Smith', 'foobar']); + }); + + it('renders the second row with the correct data', function() { + ReactableTestUtils.expectRowText(1, ['Lee Salminen', 'foobar']); + }); + }); + }); + describe('passing through HTML props', function() { describe('adding s with className to the
', function() { before(function() {