Skip to content

Commit

Permalink
Merge pull request #23 from patrick-jones/issue20
Browse files Browse the repository at this point in the history
Adds arguments for cell coordinates to `valueRenderer` and `dataRenderer`
  • Loading branch information
nadbm authored Jun 3, 2017
2 parents a3f0a04 + 4ecc60a commit 9cea185
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 25 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,18 @@ class App extends React.Component {
### Cells with underlying data

There are two values that each cell shows. The first is via ```valueRenderer``` and the second is via ```dataRenderer```. When a cell is in *edit mode*, it will show the value returned from ```dataRenderer```. It needs to return a string as this value is set in an input field.
Each of these callbacks are passed the cell value as well as the cell's coordinates in the spreadsheet. This allows you to apply formatting logic at rendering time, such as *all cells in the third column should be formatted as dates*.

```jsx
const grid = [
[{value: 5, expr: '1 + 4'}, {value: 6, expr: '6'}],
[{value: 5, expr: '1 + 4'}, {value: 5, expr: '1 + 4'}]
[{value: 5, expr: '1 + 4'}, {value: 6, expr: '6'}, {value: new Date('2008-04-10')}],
[{value: 5, expr: '1 + 4'}, {value: 5, expr: '1 + 4'}, {value: new Date('2004-05-28')}]
]
const onChange = (cell, i, j, newValue) => console.log("New expression :" + newValue)
<ReactDataSheet
data={grid}
valueRenderer={(cell) => cell.value}
dataRenderer={(cell) => cell.expr}
valueRenderer={(cell, i, j) => j == 2 ? cell.value.toDateString() : cell.value}
dataRenderer={(cell, i, j) => j == 2 ? cell.value.toISOString() : cell.expr}
onChange={}
/>
```
Expand Down Expand Up @@ -112,8 +113,8 @@ This renders a single cell with the value 5. Once in edit mode, the button will
Option | Type | Description
:--- | :---: | :---
data | Array | Array of rows and each row should contain the cell objects to display
valueRenderer | func | Method to render the value of the cell `function(cell)`. This is visible by default
dataRenderer | func | Method to render the underlying value of the cell `function(cell)`. This data is visible once in edit mode.
valueRenderer | func | Method to render the value of the cell `function(cell, i, j)`. This is visible by default
dataRenderer | func | Method to render the underlying value of the cell `function(cell, i, j)`. This data is visible once in edit mode.
onChange | func | onChange handler: `function(cell, i, j, newValue) {}`
onPaste | func | onPaste handler: `function(array) {}` If set, the function will be called with an array of rows. Each row has an array of objects containing the cell and raw pasted value. If the pasted value cannot be matched with a cell, the cell value will be undefined
onContextMenu | func | Context menu handler : `function(event, cell, i, j)`
Expand Down
11 changes: 5 additions & 6 deletions lib/DataSheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,10 @@ var DataSheet = function (_PureComponent) {

var text = range(start.i, end.i).map(function (i) {
return range(start.j, end.j).map(function (j) {
return data[i][j];
}).map(function (cell) {
var value = dataRenderer ? dataRenderer(cell) : null;
var cell = data[i][j];
var value = dataRenderer ? dataRenderer(cell, i, j) : null;
if (value === '' || value === null || typeof value === 'undefined') {
return valueRenderer(cell);
return valueRenderer(cell, i, j);
}
return value;
}).join('\t');
Expand Down Expand Up @@ -389,7 +388,7 @@ var DataSheet = function (_PureComponent) {
editing: isEditing(i, j),
reverting: isReverting(i, j),
colSpan: cell.colSpan,
value: valueRenderer(cell)
value: valueRenderer(cell, i, j)
};
if (cell.component) {
return _react2.default.createElement(_ComponentCell2.default, _extends({}, props, {
Expand All @@ -398,7 +397,7 @@ var DataSheet = function (_PureComponent) {
}));
}
return _react2.default.createElement(_DataCell2.default, _extends({}, props, {
data: dataRenderer ? dataRenderer(cell) : null,
data: dataRenderer ? dataRenderer(cell, i, j) : null,
clear: shouldClear(i, j),
rowSpan: cell.rowSpan,
onChange: _this4.onChange,
Expand Down
20 changes: 10 additions & 10 deletions src/DataSheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,14 @@ export default class DataSheet extends PureComponent {


const text = range(start.i, end.i).map((i) =>
range(start.j, end.j).map(j => data[i][j])
.map(cell => {
let value = dataRenderer ? dataRenderer(cell) : null;
if (value === '' || value === null || typeof(value) === 'undefined') {
return valueRenderer(cell);
}
return value;
}).join('\t')
range(start.j, end.j).map(j => {
const cell = data[i][j];
const value = dataRenderer ? dataRenderer(cell, i, j) : null;
if (value === '' || value === null || typeof(value) === 'undefined') {
return valueRenderer(cell, i, j);
}
return value;
}).join('\t')
).join('\n');
e.clipboardData.setData('text/plain', text);
}
Expand Down Expand Up @@ -316,7 +316,7 @@ export default class DataSheet extends PureComponent {
editing: isEditing(i, j),
reverting: isReverting(i, j),
colSpan: cell.colSpan,
value: valueRenderer(cell),
value: valueRenderer(cell, i, j),
};
if (cell.component) {
return <ComponentCell
Expand All @@ -327,7 +327,7 @@ export default class DataSheet extends PureComponent {
}
return <DataCell
{...props}
data = {dataRenderer ? dataRenderer(cell) : null}
data = {dataRenderer ? dataRenderer(cell, i, j) : null}
clear = {shouldClear(i, j)}
rowSpan = {cell.rowSpan}
onChange = {this.onChange}
Expand Down
30 changes: 27 additions & 3 deletions test/Datasheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,30 @@ describe('Component', () => {
expect(customWrapper.find('td.cell input').nodes[0].value).toEqual('=+4');
});

it('renders proper elements by column', () => {
const withDates = data.map((row, index) => [{data: new Date('2017-0' + (index + 1) + '-01')}, ...row]);
customWrapper = mount(<DataSheet
data = {withDates}
valueRenderer = {(cell, i, j) => j === 0 ? cell.data.toGMTString() : cell.data}
dataRenderer = {(cell, i, j) => j === 0 ? cell.data.toISOString() : cell.data}
onChange = {(cell, i, j, value) => data[i][j].data = value}
/>);
//expect(wrapper.find('td > span').length).toEqual(6);
expect(customWrapper.find('td > span').nodes.map(n => n.innerHTML)).toEqual(['Sun, 01 Jan 2017 00:00:00 GMT', '4', '2', 'Wed, 01 Feb 2017 00:00:00 GMT', '3', '5']);
});

it('renders data in the input properly if dataRenderer is set by column', () => {
const withDates = data.map((row, index) => [{data: new Date('2017-0' + (index + 1) + '-01')}, ...row]);
customWrapper = mount(<DataSheet
data = {withDates}
valueRenderer = {(cell, i, j) => j === 0 ? cell.data.toGMTString() : cell.data}
dataRenderer = {(cell, i, j) => j === 0 ? cell.data.toISOString() : cell.data}
onChange = {(cell, i, j, value) => data[i][j].data = value}
/>);
customWrapper.find('td').first().simulate('doubleClick');
expect(customWrapper.find('td.cell input').nodes[0].value).toEqual('2017-01-01T00:00:00.000Z');
});

it('renders a component properly', () => {
customWrapper = mount(<DataSheet
data = {[[{component: <div className={'custom-component'}>COMPONENT RENDERED</div>}]]}
Expand Down Expand Up @@ -780,16 +804,16 @@ describe('Component', () => {
customWrapper = mount(
<DataSheet
data = {data}
valueRenderer = {(cell) => cell.data}
dataRenderer = {(cell) => "=+" + cell.data}
valueRenderer = {(cell, i, j) => cell.data}
dataRenderer = {(cell, i, j) => "{" + i + "," + j + "}" + cell.data}
onChange = {(cell, i, j, value) => data[i][j].data = value}
/>
);
customWrapper.find('td').at(0).simulate('mouseDown');
customWrapper.find('td').at(3).simulate('mouseOver');

document.dispatchEvent(evt);
expect(copied).toEqual("=+4\t=+2\n=+3\t=+5");
expect(copied).toEqual("{0,0}4\t{0,1}2\n{1,0}3\t{1,1}5");
})

it('copies no data if there isn\'t anything selected', () => {
Expand Down

0 comments on commit 9cea185

Please sign in to comment.