pushing the specific table row data to a dialog in reactJS - reactjs

I have a table that retrieves data from a json called approvalsData with fields name, type, and owners. Table pulls the data just fine. And the dialog opens. But I can't figure out how to pull that row data in the dialog. Not the entire json data, just the row I am clicking on.
What am I missing here? I'm guessing a lot :)
<TableBody>
{approvalsData.map( (row, index) => (
<TableRow
key={index}
onTouchTap={this.handleApprovalDialogOpen}>
<TableRowColumn>{row.name}</TableRowColumn>
<TableRowColumn>{row.type}</TableRowColumn>
<TableRowColumn>{row.owner}</TableRowColumn>
<Dialog
modal={false}
contentStyle={dialogStyle}
open={this.state.open}
onRequestClose={this.handleApprovalDialogClose}>
<Col key={index}>
<div>Name: <span>{this.name}</span></div>
<div>Type: <span>{this.type}</span></div>
<div>Owner: <span>{this.owner}</span></div>
</Col>
</Dialog>
</TableRow>
))}
</TableBody>
UPDATE
Inspecting the source, I realized that by including the Dialog inside the loop, I was displaying a dialog for every instance of the table rows. No wonder I was just seeing the last one. The others were behind it lol. ANyway, I moved it outside of the loop but now I can't reach the table row data from the table itself. I can reach the data by pointing to the json itself. The example below is showing the first index in the json, but that is not what I want. I want to show the row that I want to click on.
<TableBody>
{approvalsData.map( (row, index) => (
<TableRow
key={index}
onTouchTap={this.handleApprovalDialogOpen}>
<TableRowColumn>{row.name}</TableRowColumn>
<TableRowColumn>{row.type}</TableRowColumn>
<TableRowColumn>{row.owner}</TableRowColumn>
</TableRow>
))}
</TableBody>
<Dialog
modal={false}
contentStyle={dialogStyle}
open={this.state.open}
onRequestClose={this.handleApprovalDialogClose}>
<Col>
<div>Name: <span>{approvalsData[0].name}</span></div>
<div>Type: <span>{approvalsData[0].type}</span></div>
<div>Owner: <span>{approvalsData[0].owner}</span></div>
</Col>
</Dialog>
See the webpackbin
Thanks in advance

I am assuming that you set the open state in handleApprovalDialogOpen callback. You can bind the callback to the index (or id if any) of the row.
// some code
onTouchTap={this.handleApprovalDialogOpen.bind(this, index)}
<Dialog
modal={false}
contentStyle={dialogStyle}
open={this.state.open}
onRequestClose={this.handleApprovalDialogClose}>
<Col>
<div>Name: <span>{approvalsData[this.state.openRowIndex].name}</span></div>
<div>Type: <span>{approvalsData[this.state.openRowIndex].type}</span></div>
<div>Owner: <span>{approvalsData[this.state.openRowIndex].owner}</span></div>
</Col>
</Dialog>
handleApprovalDialogOpen(rowIndex, event) {
this.setState({open: true, openRowIndex: rowIndex})
}

#mukesh's approach looks solid. You're probably getting undefined because you're trying to access approvalsData with an index that does not exist. Try his solution and add:
<TableBody>
{approvalsData.map( (row, index) => (
<TableRow
key={index}
onTouchTap={(e) => this.handleApprovalDialogOpen(index, e)}>
<TableRowColumn>{row.name}</TableRowColumn>
<TableRowColumn>{row.type}</TableRowColumn>
<TableRowColumn>{row.owner}</TableRowColumn>
</TableRow>
))}
</TableBody>

Related

How to animate Table Item Entry using TransitionGroup and Material UI Tables in ReactJS

I am having an issue where I can't seem to get TransitionGroup to work with Material UI ReactJS library
My expectation is pretty simple, upon entry into the table the row should be animated in like sliding into the table.
I have tried the following but this only end up scattering the table, the headers and everything becomes out of shape.
Here is what I have tried using the Material UI library for ReactJS
<TableContainer>
<Table aria-label="stats-table">
<TableHead>
<TableRow>
{...}
</TableRow>
</TableHead>
<TransitionGroup
transitionName="fade"
transitionEnterTimeout={1000}
transitionLeaveTimeout={300}
transitionAppearTimeout={1000}
transitionAppear={true}
component="tbody">
<TableBody>
{
(rowsPerPage > 0 ? games.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) : games
).map((row: Game) => (
<SimpleTableRow row={row} key={row.id}/>
))}
{
emptyRows > 0 && (
<TableRow style={{height: 53 * emptyRows}}>
<TableCell colSpan={6}/>
</TableRow>
)
}
</TableBody>
</TransitionGroup>
</TableContainer>
The moment I add the TransitionGroup, the entire table headers and body becomes scattered.
How can I make this work? Thanks
You can try to pass component={null} instead component="tbody".

How to manage noDataComponent or display no rows found in ReactTable V7

I was using the older version of React Table for last couple of months and now when i started using Latest version v7, i started facing difficulty in customizing the table while no data is found in the table to be displayed. It doesn't show any message like 'No Rows Found' which was earlier displayed in previous versions of the table. How could i render the noDataComponent.
As v7 is headless, you are responsible for the output under the varying conditions. You likely have something like map() in place to iterate over the data array similar to:
<TableBody>
{page.map((row) => {
prepareRow(row);
return (
<TableRow {...row.getRowProps()}>
{row.cells.map((cell) => {
return (
<TableCell {...cell.getCellProps()}>
{cell.render('Cell')}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
You can add some code to detect the condition where no rows are found similar to:
{page.length === 0 &&
<TableRow>
<TableCell>
No data to display
</TableCell>
</TableRow>
}

How to highlight a specific table cell in material UI table in react based on a text search

I have implemented a Material UI table and forming up the table based on the array of objects.
For example my array of objects:
[{id:1, name:abc, age: 12},{id:2, name:def, age: 13},{id:3, name:ghi, age: 14}].
This is my code for generating the table using material-ui for react.
return (
<div className={classes.root}>
{data.name}
<Paper className={classes.paper}>
<EnhancedTableToolbar handleSearch={handleSearch} value={searchValue} />
<TableContainer className={classes.container}>
<Table
className={classes.table}
aria-labelledby="tableTitle"
stickyHeader aria-label="sticky table"
>
<EnhancedTableHead
classes={classes}
order={order}
orderBy={orderBy}
onRequestSort={handleRequestSort}
/>
<TableBody>
{displaySortedData(data, getComparator(order, orderBy))
.map((row, index) => {
return (
<TableRow
hover
tabIndex={-1}
key={row.ID}
>
<TableCell style={{ textAlign: "center", cursor: "pointer" }}>
<EditIcon />
</TableCell>
<TableCell component="th" scope="row" align="right">
{row.ID}
</TableCell>
<TableCell align="left"><span className={row.name.match(searchValue) ? classes.tableCell : "" }>{row.SOR_NAME}</span></TableCell>
<TableCell align="left">{row.age}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
</Paper>
</div>
);
Now whenever user type in search box i capture that in searchValue. Based on the searchValue i change the array of objects and display the table. Now i need to highlight the text too in the table for the searched text.
For that i compare the search value in the 4rth table cell as you can see above in the code.
But my issue is that it highlights the entire column and not just the single table cell in which it found the exact search match. I understand as i am writing the comparison in the tableCell, that is why it highlights the entire column. But i only want to highlight a specific cell of that table if it exactly matches the searched text.
The EnhancedTableHead returns the table headers.
This one works for highlighting the table cell and not the word. For example if user types "match" in search field. Then with the help of following function it highlights the table cell but doesnt highlight the actual characters of the word. For example if in a table cell the word "MatchingWord", it will highlight the full word but not just "Match" in "MatchingWord"
const highlight = (classes, rowValues) =>{
if(searchValue == null || searchValue == "" || rowValues == null || rowValues == "") {
return classes.notMatchingTableCell
} else if(rowValues.toLowerCase().includes(searchValue.toLowerCase()) == true) {
return classes.tableCell
}
return classes.notMatchingTableCell
}
Here classes i pass is the actual css class for higlighting. And rowValues is the value of the row for that object. So in the material ui table part add this function in tag like this
<TableCell align="left"><span className= {highlight(classes, row.age)}>{row.age}</span></TableCell>

Onclick function for material ui tablecell in react

I have a requirement to show popovers, when clicking on table cell (used Material UI table cell). Tried adding onclick function to cell, but not able to pass the element value to the function. How can I achieve this? Below is the code snippet which used to render table.
<TableBody>
{dataObject.map((data) => (
<TableRow key={data.id}>
<TableCell>
<Button>
{data.info}
</Button>
</TableCell>
<TableCell>
{data.request}
</TableCell>
</TableRow>
))}
</TableBody>
Thanks in advance.
The <TableCell> component is eventually a td/th in your html, so you don't really have a value attached to it (it's not like a pure react component that you can just use value, or an input element that has value that you can access).
What you can do is access the element's innerHTML / textContent to access the content of the cell using the event itself:
const handleCellClick = (e) => {
console.log(e.target.textContent);
}
<TableCell onClick={handleCellClick}>{data.request}</TableCell>

react Material-UI - Table - TableBody cannot be looped

I have an issue with react material-UI's table component.
I wanna create a table where the content is shown dynamically based on the data it receives. So I'm looping through the data, each time creating a new TableBody as the root element. But when I'm looping through the data, it only displays the first (or maybe the last) cycle in the loop.
Here is my code from the render method (the code is vastly simplified):
<Table selectable={ false }>
<TableHeader displaySelectAll={false} adjustForCheckbox={false}>
<TableRow>
<TableHeaderColumn colSpan={3}>{ this.i18n('Filename') }</TableHeaderColumn>
</TableRow>
</TableHeader>
{
files.map((file, idx) => (
<TableBody displayRowCheckbox={ false } key={idx}>
<TableRow>
<TableRowColumn>{ file.name }</TableRowColumn>
<TableRowColumn colSpan={2}><Button variant="flat" data-name='cancel' color="primary">{ this.i18n('Delete') }</Button></TableRowColumn>
</TableRow>
<TableRow />
<TableRow>
<TableRowColumn colSpan={3}>
<RadioButtonGroup name='caption' />
<RadioButton />
<RadioButton />
</RadioButtonGroup>
<Input type='text' />
</TableRowColumn>
</TableRow>
</TableBody>
))
}
</Table>
This only outputs one cycle in the in the loop, even though the data contains several loops.
NOTE::: The code works, when I replace the material-UI with a html table, then it works as expected.
this is because you create a tableBody every item loop, try to set the loop right after < TableBody > tag, because you want to loop < TableRow > not < TableBody >

Resources