Material Table Search doesn't work for custom column - reactjs

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.

Related

How to show name of first item followed by the number of total items present in the row of expandable table in react js?

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:

How to select the desired input field for filtering in React Data Grid

I am trying to write some tests using Cypress with Reactjs (both latest versions). It seems like there is nothing I can select these input fields of filtering because they all look the same. Is there a way to put id/class names to these fields? I am both new to React and Cypress. Thanks
https://codesandbox.io/s/w6jvml4v45?from-embed=&file=/src/index.js
import React, { useState } from "react";
import ReactDOM from "react-dom";
import ReactDataGrid from "react-data-grid";
import { Toolbar, Data } from "react-data-grid-addons";
import createRowData from "./createRowData";
import "./styles.css";
const defaultColumnProperties = {
filterable: true,
width: 120
};
const selectors = Data.Selectors;
const columns = [
{
key: "id",
name: "ID"
},
{
key: "title",
name: "Title"
},
{
key: "firstName",
name: "First Name"
},
{
key: "lastName",
name: "Last Name"
},
{
key: "email",
name: "Email"
},
{
key: "street",
name: "Street"
},
{
key: "zipCode",
name: "ZipCode"
},
{
key: "date",
name: "Date"
},
{
key: "jobTitle",
name: "Job Title"
},
{
key: "catchPhrase",
name: "Catch Phrase"
},
{
key: "jobArea",
name: "Job Area"
},
{
key: "jobType",
name: "Job Type"
}
].map(c => ({ ...c, ...defaultColumnProperties }));
const ROW_COUNT = 50;
const handleFilterChange = filter => filters => {
const newFilters = { ...filters };
if (filter.filterTerm) {
newFilters[filter.column.key] = filter;
} else {
delete newFilters[filter.column.key];
}
return newFilters;
};
function getRows(rows, filters) {
return selectors.getRows({ rows, filters });
}
function Example({ rows }) {
const [filters, setFilters] = useState({});
const filteredRows = getRows(rows, filters);
return (
<ReactDataGrid
columns={columns}
rowGetter={i => filteredRows[i]}
rowsCount={filteredRows.length}
minHeight={500}
toolbar={<Toolbar enableFilter={true} />}
onAddFilter={filter => setFilters(handleFilterChange(filter))}
onClearFilters={() => setFilters({})}
/>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Example rows={createRowData(50)} />, rootElement);
I would Use This specific attribute syntax to select them by key value:
cy.get(`input[key="${targetValue}"]`)
.then(element => {
//My code
})

Semantic react ui dropdown multiple selection: option to Select All

I am developing a react application based on hooks and for multi select dropdown am using react semantic ui Dropdown. But there is no option to Select All items. How to acheieve this? On click of Select All all the items should be selected and not be shown in the dropdown:-
import React, { useState } from "react";
import { Dropdown } from "semantic-ui-react";
const options = [
{ key: "select all", text: "Select All", value: "Select All" },
{ key: "angular", text: "Angular", value: "angular" },
{ key: "css", text: "CSS", value: "css" },
{ key: "design", text: "Graphic Design", value: "design" },
{ key: "ember", text: "Ember", value: "ember" },
{ key: "html", text: "HTML", value: "html" },
{ key: "ia", text: "Information Architecture", value: "ia" },
{ key: "ux", text: "User Experience", value: "ux" }
];
const DropdownExampleMultipleSelection = () => {
const [selectedItems, setSelectedItems] = useState([]);
const onChange = (event, data) => {
setSelectedItems(data.value);
if (data.value == "Select All") {
console.log(data);
console.log(event.target);
}
};
return (
<Dropdown
placeholder="Skills"
clearable
fluid
multiple
selection
options={options}
onChange={onChange}
value={selectedItems}
label="Skills"
/>
);
};
export default DropdownExampleMultipleSelection;
You need to check for the last selected items with event.target.textContent and add all options if this is selected.
const onChange = (event, data) => {
if(event.target.textContent === 'Select All') {
setSelectedItems(data.options.map(d => d.value))
} else {
setSelectedItems(data.value);
}
};

Ant Design for React : Show/Hide particular column

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"));

React-Data-Grid only displays 9 rows

I am loading a react-data-grid with a data source that is populated row by row (a row is added once a second). Once it gets to 9 rows it stops adding rows. I am also having another problem where the grid will not show up until I change the zoom on the screen. It is blank beforehand. Here is my grid element
import React, { Component } from 'react';
import DataGrid from 'react-data-grid';
import 'react-data-grid/dist/react-data-grid.css';
const columns = [
{ key: 'timeStamp', name: 'Date/Time' },
{ key: 'gpsAccuracyValue', name: 'GPS Accuracy' },
{ key: 'speedMph', name: 'Speed' },
{ key: 'battery', name: 'Battery' },
{ key: 'id', name: 'id' },
];
const rows = [
{ id: 0, title: 'Example' },
{ id: 1, title: 'Demo' }
];
class TestGrid extends Component {
render(){
return (
<div>
<DataGrid
columns={columns}
rows={this.props.data}
rowsCount={this.props.data.length}
minHeight={500}
/>
</div>
);
}
}
export default TestGrid;
I pass in the data like this
<TestGrid data={this.props.deviceData} />
CodeSandbox
Adding style={{ height:500 }} seems to have fixed a similar problem I was having and displays more than 9 rows.

Resources