I need a bit of help here, In an Ant Design table, I need to hide/show a particular column of a table depending on a state value. In the given sandbox link, I need to hide the surname column whenever the switch is Off and show when the switch is On.
Please, someone, look into this, and help me out.
Reference: https://codesandbox.io/s/purple-sun-1rtz1?file=/index.js
There is a working code, but it should be more customize, interactivize, and refactorize depending on your need:
// You can also modify the data in the `handleChnage`
// Or conditionally display it like here:
class EditableTable extends React.Component {
state = {
surNameShow: false
};
constructor(props) {
super(props);
this.columns = [
{
title: "Name",
dataIndex: "name",
width: "30%"
},
{
title: "Surname",
dataIndex: "surname",
width: "30%"
}
];
this.state = {
dataSource: [
{
key: "0",
name: "Edward 1",
surname: "King 1"
},
{
key: "1",
name: "Edward 2",
surname: "King 2"
}
]
};
}
handleChnage = key => {
this.setState({ surNameShow: !this.state.surNameShow }, () => {
console.log(this.state.surNameShow);
});
};
render() {
const { dataSource } = this.state;
const columns = this.columns;
return (
<div>
<p className="mr-3"> Show surname</p>
<Switch onChange={() => this.handleChnage()} />
<Table
bordered
dataSource={dataSource}
columns={
this.state.surNameShow
? columns
: columns.filter(ea => ea.dataIndex !== "surname")
}
pagination={false}
/>
</div>
);
}
}
ReactDOM.render(<EditableTable />, document.getElementById("container"));
Related
As shown in the picture, I have created a similar collapsible table, but I am unable to display the number of items in the collapsible rows. I am referring to the headings written in blue colour (in the picture)
Can someone help me to understand, how I can display the name of first items followed by the number of remaining items in heading of each main row ( for eg ( basketball..+2). Also I am using api call to fetch data in the table
enter code here
export const columns = [
{
Header: () => (
<div />
),
accessor: 'name',
maxWidth: 300,
Cell: row => (
<div className='first-column'>{row.value}</div>
)
}
];
export const subComponent = row => {
return (
<div>
{row.original.types.map((type, id) => {
return (
<div className='subRow' key={ id }>{ type.name }</div>
);
})}
</div>
);
};
export const data = [
{
id: '12345',
name: 'sports',
types: [
{
name: 'basketball',
id: '1'
},
{
name: 'soccer',
id: '2'
},
{
name: 'baseball',
id: '3'
}
]
},
{
id: '678910',
name: 'food',
types: [
{
name: 'pizza',
id: '4'
},
{
name: 'hamburger',
id: '5'
},
{
name: 'salad',
id: '6'
}
]
}
]
First, your columns have to use useMemo hooks. You can read the details here.
const columns = useMemo(() => [
...
],[])
Next, change the types property into subRows in your data so the subRows rows can be auto rendered and no additional subRow component required.
const data = [
{
id: "12345",
name: "sports",
subRows: [ // <---- change types into subRows
{
name: "basketball",
id: "1",
},
...
],
},
...
];
The subRows informations is also required to get the remaining items in heading. Here, we grab and describe the information at column's Cell
{
Header: () => <div />,
accessor: "name",
maxWidth: 300,
Cell: ({ row }) => {
// we can get subRows info here after change types into subRows
const { subRows } = row,
// describe the required information here
isSubRow = subRows[0] ? false : true,
firstSubRowName = subRows[0] ? subRows[0].original.name : "",
remainingSubRowsLength = subRows[1] ? `..+${subRows.length - 1}` : "";
return (
<span>
{row.original.name}
// conditionally render the additional info
{!isSubRow && (
<span
style={{ color: "blue" }}
>{` (${firstSubRowName}${remainingSubRowsLength})`}</span>
)}
</span>
);
}
}
And the final code will become:
import { useMemo } from "react";
import { useTable, useExpanded } from "react-table";
const data = [
{
id: "12345",
name: "sports",
subRows: [
{
name: "basketball",
id: "1"
},
{
name: "soccer",
id: "2"
},
{
name: "baseball",
id: "3"
}
]
},
{
id: "678910",
name: "food",
subRows: [
{
name: "pizza",
id: "4"
},
{
name: "hamburger",
id: "5"
},
{
name: "salad",
id: "6"
}
]
}
];
export default function App() {
const columns = useMemo(
() => [
{
Header: () => null,
id: "expander",
Cell: ({ row }) => {
return (
<span {...row.getToggleRowExpandedProps()}>
{row.depth === 0 && (row.isExpanded ? "▼" : "►")}
</span>
);
}
},
{
Header: () => <div />,
accessor: "name",
maxWidth: 300,
Cell: ({ row }) => {
const { subRows } = row,
isSubRow = subRows[0] ? false : true,
firstSubRowName = subRows[0] ? subRows[0].original.name : "",
remainingSubRowsLength = subRows[1] ? `..+${subRows.length - 1}` : "";
return (
<span>
{row.original.name}
{!isSubRow && (
<span
style={{ color: "blue" }}
>{` (${firstSubRowName}${remainingSubRowsLength})`}</span>
)}
</span>
);
}
}
],
[]
);
const { getTableProps, getTableBodyProps, rows, prepareRow } = useTable(
{
columns,
data
},
useExpanded
);
return (
<>
<h1>React Table v.7 SubRows</h1>
<br />
<table
{...getTableProps()}
style={{ borderCollapse: "collapse", width: "50%" }}
>
<tbody {...getTableBodyProps}>
{rows.map((row, index) => {
prepareRow(row);
return (
<tr
{...row.getRowProps}
key={index}
style={{
border: "1px solid black",
height: "30px",
background: row.subRows[0] ? "#e9ebfb" : "#fff"
}}
>
{row.cells.map((cell, i) => {
return (
<td {...cell.getCellProps()} key={i}>
{cell.render("Cell")}
</td>
);
})}
</tr>
);
})}
</tbody>
</table>
</>
);
}
Here is the example at codesanbox:
OK, so Im getting this error when trying to return some data from my web api. Ive tried all as suggested on other similar posts but cant get this working. Any help appreciated.
Objects are not valid as a React child. If you meant to render a collection of children, use an array instead.
clg(records) returns this:
[{
id:1,
Listing: {id: 2, title: 'Testtt'},
ListingId: 2
},
{
id:2,
Listing: {id: 3, title: 'hell world'},
ListingId: 3
}]
here is my reactjs code:
class Products extends Component {
constructor(props) {
super(props);
this.columns = [
{
key: "id",
text: "Id",
className: "id",
align: "left",
sortable: true,
},
{
id:"ListingId"
text: "Merchant ID",
className: "name",
align: "left",
sortable: true,
},
}
];
this.state = {
records: []
};
this.getData = this.getData.bind(this);
}
componentDidMount() {
this.getData()
};
componentWillReceiveProps(nextProps) {
this.getData()
}
getData() {
axios
.get("/api/products")
.then(res => {
this.setState({ records: res.data})
})
.catch()
}
render() {
const {records}=this.state;
console.log(records);
return (
<div>
<ReactDatatable
records={this.state.records}
columns={this.columns}
loading='true'
/>
</div>
);
}}
Currently its displaying ListingId in the column, how can i display the Listing title instead?
i am currently using this package :
https://www.npmjs.com/package/#ashvin27/react-datatable
Here is the solution to my question
{
key:'ListingId',
text: "Column Title",
className: "name",
align: "left",
sortable: true,
cell: record => {
console.log(record)
return (
<span>{record.Listing.title}</span>)
}
},
Folks,
I have a mat table with a custom column as "Items" , this can have multiple values.
I can render it as comma separated values however for better look and feel , I am rendering each item as chip.
Now the issue is mat table default search doesn't work on this field.
Any help would be greatly appreciated.
import React, { Fragment, useState } from "react";
import MaterialTable from "material-table";
import { Box, makeStyles, Chip } from "#material-ui/core";
const useStyles = makeStyles((theme) => ({
chip: {
margin: 2
},
noLabel: {
marginTop: theme.spacing(3)
},
}));
const originalData = [
{
id: "1",
productName: "Meat",
items: [
{id : 1, name : "chicken"},
{id : 2, name : "pork" },
{id : 3, name : "lamb" }
]
},
{
id: "2",
productName: "Vegetables",
items: [
{id : 1, name : "Okra"},
{id : 2, name : "Pumpkin" },
{id : 3, name : "Onion" }
]
},
];
export default function MatTableTest(props) {
const [data, setData] = useState(originalData);
const classes = useStyles();
const tableColumns = [
{ title: "id", field: "id", editable : "never" },
{ title: "Product Name", field: "productName" , editable : "never" },
{ title: "Item", field: "items", editable : "never",
render: rowData => {
return (
<Box className="box" id="style-7">
{ rowData.items.map((exprt) => <Chip
key={exprt.id}
label={exprt.name}
className={classes.chip}
/>)}
</Box>
);
}
},
];
return (
<Fragment>
<MaterialTable
columns={tableColumns}
data={data}
title="Material Table - Custom Colum Search"
/>
</Fragment>
);
}
There is a prop called customFilterAndSearch where you can define a custom filter function. You can define what row data you wish to match for in there. Here is an example from an issue created in Github repo.
I want to customize the row hat data in mui-datatble in such a way that if I get Yes in the option, background color should be Red and if I say No, background color should be Blue. I am using mui-datatable first time.
I am unable to use customRowRender or customRender. How do we use it in mui-datatable
import React from 'react';
import MUIDataTable from "mui-datatables";
class Datatable extends React.Component {
render() {
const columns = [
{
name: "name",
label: "Name",
options: {
filter: true,
sort: true,
customRowRender:(data, dataIndex, rowIndex) => {
console.log('data' + data);
return (
<div>
{data}{' '}{dataIndex}{' '}{rowIndex}
</div>
);
}
}
},
{
name: "company",
label: "Company",
options: {
filter: true,
sort: false,
}
}
];
const data = [
{ name: "Joe James", company: "Test Corp" },
{ name: "John Walsh", company: "Test Corp" }
];
const options = {
filterType: 'checkbox',
};
return (
<React.Fragment>
<MUIDataTable
title={"Employee List"}
data={data}
columns={columns}
options={options}
/>
</React.Fragment>
);
}}
export default Datatable;
I should be able to render data in customRender where I will add a conditional render with a <div> and style depending on Yes/No
You have put the customRowRender property in the columns object, according to the doc it should be in the options object :
const options = {
filterType: 'checkbox',
customRowRender:(data, dataIndex, rowIndex) => {
console.log('data' + data);
return (
<div>
{data}{' '}{dataIndex}{' '}{rowIndex}
</div>
);
}
};
// render
<MUIDataTable
title={"Employee List"}
data={data}
columns={columns}
options={options}
/>
But this is for rendering a custom row, if you want to render a custom column, then you can use customBodyRender property in the columns object.
I was playing around with React for the first time and trying to figure out how to make tabs. I found an outline of the code that looks simple and clean enough (do correct me if I'm wrong though, please), but I don't know how to show the content of the tabs outside of the 'constructor'. As I want the tab content to be more than just a couple of words, and the current code seems constricting.
This is the part that I'm talking about:
constructor(props) {
super(props);
this.state = {
activeTabIndex: 0,
initialData: [
{
label: 'Tab 1',
content: 'Content 1',
},
{
label: 'Tab 2',
content: 'Content 2',
},
{
label: 'Tab 3',
content: 'Content 3',
},
],
};
this.handleTabClick = this.handleTabClick.bind(this);
}
How do I pull the content outside of this, if I have too much content to be put inside that? Here is the entire code outline: link. Any suggestions/links are welcome.
And I apologize if I'm explaining this wrong, I'm still trying to figure stuff out. Thanks!
Just create a Component you want to render in Tab Content and assign it to content.
import React, { Component } from "react";
import Tabs from "./Tabs";
import Content from "./Content";
export default class TabView extends Component {
constructor(props) {
super(props);
this.state = {
activeTabIndex: 0,
initialData: [
{
label: "Tab 1",
content: <TabContent />
},
{
label: "Tab 2",
content: "Content 2"
},
{
label: "Tab 3",
content: "Content 3"
}
]
};
this.handleTabClick = this.handleTabClick.bind(this);
}
handleTabClick(index) {
this.setState({
activeTabIndex: index
});
}
render() {
const { initialData, activeTabIndex } = this.state;
const activeItem = this.state.initialData[activeTabIndex];
return (
<div>
<Tabs
handleTabClick={this.handleTabClick}
data={this.state.initialData}
activeTabIndex={activeTabIndex}
/>
<Content content={activeItem.content} />
</div>
);
}
}
const TabContent = () => (
<div>
<p>I am here</p>
</div>
);