nadbm / react-datasheet Goto Github PK
View Code? Open in Web Editor NEWExcel-like data grid (table) component for React
Home Page: https://nadbm.github.io/react-datasheet/
License: MIT License
Excel-like data grid (table) component for React
Home Page: https://nadbm.github.io/react-datasheet/
License: MIT License
Hello! Great react-datasheet. Really cool =)
Recently we release first public version of this project.
https://github.com/OpusCapitaBES/js-react-showroom-client
It allows to write documentation in markdown and run all docs in sandbox with code examples.
It often useful to have possibility to play with components at web page before use it in project.
Do you interested in adding interactivity to your examples page?)
I can make it and send you pull-request. Of course it can use your brand styles.
It would be useful to be able to specify column widths. These could be applied using a style
attribute when rendering the cells. I can do a PR for this.
Hi! I just came across this and was curious if Touch/Mobile support was on your roadmap or radar for this project?
Hi there! :)
I need a fixed header and columns and scroll over the datasheet so I came up with this aproach to solve the problem. It's still a work in progress. I create a new component and separate it from the old one, then I move the logic that manage the onPaste, onCopy and onKeyPress to another file to share the methods between the two components. All though I did some refactoring, test, etc.
All ideas are welcome.
What do you think? There're still work to do but the FixedDatasheet has this new features while keeping the old component working exactly as before. There is an example by the end of the page.
example: https://sediug.github.io/react-datasheet#fixed-datasheet
branch: https://github.com/Sediug/react-datasheet/tree/feature/fixed-header-and-columns
Or is there an easy way to get copy-n-paste working?
When I paste 20 rows with 10 columns (a modest amount of data) takes more than 10 seconds to render and it's all due to scripting.
If I introduce the method shouldComponentUpdate
to render only every 500 ms, pasting data is twice as fast, but still very slow. It seems the cause is setting state for each a cell during the onChange
method (the loop through the grid's rows and columns).
To get around this, I set up a separate textarea
to paste the Excel data. I parse the pasted string to get rows = string.split('\r\n')
and then cells = rows[i].split('\t')
. I get the pasted grid
and this.setState({ grid })
. There is no delay (but it replaces the whole grid, not just a portion beginning at a selected cell).
Is there a way to paste into a cell but with improved speed? Possibly without setting state until the new grid has been processed?
Please share any benchmarking & performance stats around this library. Interested in knowing how far we can stretch this one.
While editing, if the user hits the escape key then you should exit edit mode and the original, pre-editing value should be restored.
I want to overwrite the default styles, how can i do it
Nothing major, but I noticed the Cell Options forceComponent reads:
Renders whats in component at all times, even when not in edit mode
It should read:
Renders what's in component at all times, even when not in edit mode
I would like to show some properties outside the component regarding the selected cell. I managed to trigger an event by overriding the cell, but when I click outside the component the selection is gone.
How about something like this:
onSelected(selected) {
this.setState({ selected })
}
<DataSheet
...
selected={this.state.selected}
onSelected={onSelected}
/>
This seems related to #56. When deleting a multi-cell selection, onChange
gets called multiple times within a tight loop. This can cause a lot of unnecessary re-rendering when you update your state (or redux reducer, etc) from within a loop. I have even seen a hard to reproduce situation in which only the last cell in the range was deleted, I think because setState
doesn't always immediately update the state:
setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall.
I think the solution is to support a version of onChange
that takes an array of changed cells rather than just the one, as it does now.You have already taken a step towards this with onPaste
, but that doesn't cover mass deletions. We can't change the arguments to onChange
without breaking existing code, so I suggest
onChanges([{cell, i, j, newValue}, {cell, i, j, newValue}, {cell, i, j, newValue}, ...])
I'm not married to that name, but I can't think of anything better right now. If the user supplies onChanges
we call that instead of onChange
, just like onPaste
works now.onChange
and onPaste
so that there is a single handler no matter how many cells are affected.If you like the idea I can PR it.
I'm trying to make some changes on a branch and test it with the examples in docs/examples
. I tried running npm run build
and also npm run build:watch
then opening docs/build/index.html
but I'm getting 404s for the JS and CSS bundles. Looking into this I also noticed that docs/build
is not really in sync with docs/public
-- for example the <title>
element in docs/build
says "React App" whereas the one in docs/public
says "React Datasheet Component". Anyway, any pointers would be greatly appreciated!
Focus on the first cell by default, to start working on the spreadsheet without the intervention of a mouse.
Getting this warning when using cellRenderer.
Warning: Received `false` for a non-boolean attribute `editing`.
If you want to write it to the DOM, pass a string instead: editing="false" or editing={value.toString()}.
If you used to conditionally omit it with editing={condition && value}, pass editing={condition ? value : undefined} instead.
in td (created by cellRenderer)
in cellRenderer (created by DataCell)
in DataCell (created by DataSheet)
in tr (created by Row)
in Row (created by DataSheet)
in tbody (created by Sheet)
in table (created by Sheet)
in Sheet (created by DataSheet)
in span (created by DataSheet)
in DataSheet (created by DataTable)
in DataTable (created by Connect(DataTable))
in Connect(DataTable) (created by App)
in div (created by App)
in div (created by App)
in App
in div
in Provider
My renderer looks like this:
const cellRenderer = (props) => {
const {
row,
col,
cell,
children,
...rest
} = props;
let style;
if (row === 0) {
style = {
padding: '3px',
fontSize: '20px',
width: '60px',
};
}
// if (col === 0) {
// attributes.title = cell.label
// }
return (
<td {...rest} style={style}>
{props.children}
</td>
);
};
bug found after upgraded to v1.3.2 from v1.2.11.
I'm using a <select ... />
inside a cell, however, datasheet's onChange
is called when cell loses focus, so that empty value overrides my select
input.
How can I display a scroll bar for too many rows ?
cheers
Just a small change on the exemple for Cells with underlying component
It has an extra brace on <button onClick={() => console.log("clicked")}}>
In many functions of the DataSheet component there're calls to this.props.onChange
without checking that this prop exist. I think it should be set as required in the propTypes section onChange: PropTypes.func.isRequired
.
Example of the commented before:
onChange(i, j, val) {
this.props.onChange(this.props.data[i][j], i, j, val);
this.setState({editing: {}});
}
Hi,
is there a read-only mode for the grid?
So no change operations, but selection, copy, navigation etc. ?
Thank you.
The issue I have is I have users pasting data where the intended rows are separated by something besides newlines, and the cells are separated by something besides tabs. I'm wondering if you would be open to adding a parsePaste
prop or similar, to customize how we initially parse data that a user pastes in. Basically I want to be able to customize the following code:
// (this starts at L103 in DataSheet.js)
const pasteData = e.clipboardData
.getData('text/plain')
.split(/\r\n|\n|\r/)
.map((row) => row.split('\t'));
I propose something along the lines of:
function defaultParsePaste (str) {
return str.split(/\r\n|\n|\r/).map((row) => row.split('\t'));
}
// later on...
const parser = this.props.parsePaste || defaultParsePaste
const pasteData = parser(e.clipboardData.getData('text/plain'))
with the contract that a user-provided parsePaste
(or whatever we call it) return a 2d array of strings.
I'd be happy to open a PR if you would accept it.
Win newline convention is \r\n. However this code splits data into data with empty rows.
react-datasheet/src/DataSheet.js
Line 105 in 617890a
The down arrow key already does this, but in Excel during edit the Enter key has the same effect as the down arrow key, which I think end users expect but doesn't do right now in react-datasheet.
{
"Id": "GridData",
"Columns": [
{
"Key": "Id",
"Name": "Id",
"Width": 40,
"Fixed": true
},
{
"Key": "task",
"Name": "Title",
"Width": 100,
"Fixed": true
},
{
"Key": "priority",
"Name": "Priority",
"Width": 125
},
{
"Key": "issueType",
"Name": "Issue Type",
"Width": 150
},
{
"Key": "taskInfo",
"Name": "Task info",
"Width": 400
},
{
"Key": "complete",
"Name": "% Complete",
"Width": 200
},
{
"Key": "startDate",
"Name": "Start Date",
"Width": 300
},
{
"Key": "completeDate",
"Name": "Expected Complete",
"Width": 300
},
{
"Key": "notes",
"Name": "Task notes",
"Width": 300,
"RightFixed":false
}
],
"Table::Employee": [
{
"Id": 1,
"priority": "OrangeRed",
"issueType": "Major",
"task": "Task 1",
"complete": 100,
"taskInfo": "Test",
"startDate": "Sun May 08 2016 13:59:24 GMT+0530 (IST)",
"completeDate": "Fri Jun 24 2016 17:54:05 GMT+0530 (IST)",
"notes": ""
},
{
"Id": 2,
"priority": "OrangeRed",
"issueType": "Major",
"task": "Task 1",
"complete": 100,
"taskInfo": "Test",
"startDate": "Sun May 08 2016 13:59:24 GMT+0530 (IST)",
"completeDate": "Fri Jun 24 2016 17:54:05 GMT+0530 (IST)",
"notes": ""
},
{
"Id": 3,
"priority": "OrangeRed",
"issueType": "Major",
"task": "Task 1",
"complete": 100,
"taskInfo": "Test",
"startDate": "Sun May 08 2016 13:59:24 GMT+0530 (IST)",
"completeDate": "Fri Jun 24 2016 17:54:05 GMT+0530 (IST)",
"notes": ""
},
{
"Id": 4,
"priority": "OrangeRed",
"issueType": "Major",
"task": "Task 1",
"complete": 100,
"taskInfo": "Test",
"startDate": "Sun May 08 2016 13:59:24 GMT+0530 (IST)",
"completeDate": "Fri Jun 24 2016 17:54:05 GMT+0530 (IST)",
"notes": ""
},
{
"Id": 5,
"priority": "OrangeRed",
"issueType": "Major",
"task": "Task 1",
"complete": 100,
"taskInfo": "Test",
"startDate": "Sun May 08 2016 13:59:24 GMT+0530 (IST)",
"completeDate": "Fri Jun 24 2016 17:54:05 GMT+0530 (IST)",
"notes": ""
}
,
{
"Id": 6,
"priority": "OrangeRed",
"issueType": "Major",
"task": "Task 1",
"complete": 100,
"taskInfo": "Test",
"startDate": "Sun May 08 2016 13:59:24 GMT+0530 (IST)",
"completeDate": "Fri Jun 24 2016 17:54:05 GMT+0530 (IST)",
"notes": ""
},
{
"Id": 7,
"priority": "OrangeRed",
"issueType": "Major",
"task": "Task 1",
"complete": 100,
"taskInfo": "Test",
"startDate": "Sun May 08 2016 13:59:24 GMT+0530 (IST)",
"completeDate": "Fri Jun 24 2016 17:54:05 GMT+0530 (IST)",
"notes": ""
}
]
}
This Kind of data structure how can i use react data sheet
Despite original delay during first render, I've also got few seconds delay when trying to use key navigation or change a cell.
How could I make it fast?
Also how could I show eg 20 rows on screen and use scroll or key navigation to show the rest?
is there any option to select row with checkbox on mouse hover
like this
http://adazzle.github.io/react-data-grid/examples.html#/row-reordering
I have been looking into adding row drag and drop using react-dnd. I'm hampered by the fact that the rendering function for the datasheet is a bit of a black box. For example, react-dnd would really like to wrap each tr
in order to hook up event handling and drag representation, etc.
Outside of react-dnd, it would be nice to be able to heavily customize rendering (such as putting custom controls at the beginning of the row, or a custom header component) without having to change the data model.
I'd like to extract out the current rendering functions and allow you to specify overrides via properties. The default would be to just keep doing what it's doing. I can do a PR for this.
Can we use react-datasheet cell selection features in to https://github.com/adazzle/react-data-grid
in this lib
Not gonna call the current behavior a "bug" but i figure a thread on what should be done for overflow is a worthwhile discussion.
Does it makes sense to truncate (overflow hidden) when the next cell is filled, but not when empty? What if it is going to overlap a a third cell that is filled... do we allow overflow into the second empty cell then hide when reaching the third?
I'm not totally sure if this is a bug or just something improper with the way I'm going about this. I'm trying to auto-generate a 10-by-10 grid on init:
class Base extends React.Component {
constructor(props) {
super(props)
this.state = {
grid: Array(10).fill(Array(10).fill({})),
}
this._handleChange = this._handleChange.bind(this)
}
_handleChange(cell, colI, rowJ, value) {
this.setState({
grid: this.state.grid.map((col) =>
col.map((rowCell) =>
(rowCell === cell) ? ({value: value}) : rowCell
)
)
})
}
render() {
return (
<DataSheet
data={this.state.grid}
valueRenderer={(cell) => cell.value}
onChange={this._handleChange} />
)
}
}
export default Base
but when I do this, if I type anything into a cell, the entire grid gets filled with that value. After that it behaves as expected.
I can get any truthy or falsy value for that initial cell:
grid: Array(10).fill(Array(10).fill({value: null}))
grid: Array(10).fill(Array(10).fill({value: 0}))
grid: Array(10).fill(Array(10).fill({value: 1}))
all do the same thing.
It would be useful to include row and column indices as arguments to the valueRenderer
and dataRenderer
callbacks. That would make it easy to make a model to say (for example), "column 3 is formatted as Chinese yuan". The revised signature would be valueRenderer(cell, row, col) => string
Hi @nadbm, I'm looking for an example where you use a react-select component and you're able to clear the cell value with the delete
or backspace
key. Is this possible? I tried adapting the example on https://nadbm.github.io/react-datasheet/ and I was unable to do get that to work.
I want to be able to override DataSheet events but don't see a way to do this currently. In particular, I want to disable the default behavior for when you click and drag across multiple cells (basically I want to have it just highlight the cell you clicked and that's it: I have the grid in a draggable div and the two drags conflict with one another).
In the constructor for DataSheet it's as easy as _this.onMouseOver = (_this.props.onMouseOver || _this.onMouseOver).bind(this)
for instance, and then if you do <ReactDataSheet onMouseOver={myFunction}/>
then whatever myFunction is will override the default behavior.
I think I'm going to go ahead and implement this in my fork soon because it's something I need for a project I'm working on. I'll create a PR from there and if this isn't a desired feature or my implementation sucks, feel free to reject the PR or suggest a different approach and I might have time to do that myself.
Fixed and created PR. Basically onChange lists params colI
(2nd param) and rowJ
(3rd) in the documentation. I is typically used with rows and J with cols, and in the code itself, the 2nd param is a row identifier even if in the docs it's called colI
, and similar for 3rd param, which is actually a column identifier.
I'm creating custom cheet by assinging ValueViewer as show in
Sheet with custom renderers
Following the example
the thing is that i want to create a borderless, lineless sheet for my custom design.
should i do by overriding css? if then How?
my custom sheet photo -> https://imgur.com/a/Nyho6
Been trying to implement sending DB requests on change to the data grid but the function onChange is not being invoked.
Tried using this in the constructor
this.onChange = this.onChange.bind(this);
with the onChange={this.onChange}
Managed to invoke the function, but its giving different errors per invoking if per cell change invoke or, by datasheet invoke.
as example if I delete a row using my delete keystroke it will give me
Uncaught TypeError: Cannot read property 'key' of null which I guess because its not getting any cell correctly in function call.
Meanwhile invoking from the component using select gives another error.
Copy/Paste from Paste to React-DataSheet to Excel
This seems to work well
Copy/Paste from Paste to Excel to React-DataSheet
This works when if I am only copying data from one row, but more than one row does not paste properly into React-DataSheet is not working. It mashes all the data into a single row.
OS: macOS 10.12.3
Browser: Version 56.0.2924.87 (64-bit)
Excel: 15.31
Is it possible to focus or pass the enter key event to the custom component when in editing mode (forceComponent is set to true) ?
My use case:
I have a custom Select options component inside the cell, with forceComponent: true. I would like to capture the enter key event/focus and open the Select dropdown.
First thing, I wanted to say thank you for building and contributing such a high quality component. I'm playing around with it now, and it's quite impressive.
I was was looking to integrate this into a react project that used typescript, and I was hoping to get all the typescript goodness that I'm used to. I didn't see any definition files in this project or any existing definitions on @types, and I was wondering if anyone has hit this need before and if there are any solutions that already exist?
If not, would you be open to a PR to add types? I could also try to contribute to @types, but it seems like it might be a better experience for everyone if they were integrated into the core library.
Maybe the expected behavior should be that the cursor within the editing field moves left/right. In any case, #36 would make this customizable.
If you set a custom className for any cell with your own styles and edit the cell (change its value) on the datasheet that cell's classes are reset.
Example:
Bottom border on some cells with a custom class.
And after editing any of those cells:
Cell clases while selected:
Classes after editing:
How do you approach adding a row in the middle of two rows? I've read there's a system of key of each cell, so if you add a row in the middle of two, you probably need to change every key, no?
If the text is too long in two adjacent cell, the text will overlay each other and hard to distinct.
Is there a way to support text-overflow?
I have tried text-overflow to but it seems not working.
Hi,
I just tried to integrate the react-datasheet component into my project where I faced some issues with regard to rendering the component. What could be the reason for that? I saw the last commit in the react-datasheet project was about 23 hours ago. I also followed the given example step by step from the basic usage section. I appreciate any help.
fzoozai
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.