Material-UI DataGrid: Removing a row from state causes Cannot read property error - datagrid

I have a material UI Datagrid as follow:
<DataGrid
className={classes.datagrid}
page={page}
pageSize={rowsPerPage}
rows={rows}
columns={columns}
sortModel={sortModel}
rowCount={meta.total}
loading={store.panels.loading}
rowsPerPageOptions={
[5, 10, 25, 50] as PageSizeOptions[]
}
disableSelectionOnClick
onPageSizeChange={changePageSize}
autoHeight
onPageChange={handlePageChange}
onSortModelChange={updateSort}
components={{
loadingOverlay: LoadingOverlay,
noRowsOverlay: NoRowOverlay,
}}
/>
I have an observable mobx array. const rows = [inherited mobx array from global store]
I then delete a row from the array on the global store.
I receive the following error:
TypeError: Cannot read property 'id' of undefined
(anonymous function)
node_modules/#material-ui/data-grid/dist/index-esm.js:15
etc...
The mobx array is an array of objects [ { id: 1, name: "bob" }, etc... ]
The columns:
const columns: ColDef[] = [
{ field: 'id', hide: true },
{
headerName: 'Name',
field: 'name',
width: 110,
},
];
This error only occurs when I try to remove a row.
Adding, fetching or updating works fine.
It seems to be a bug with MUI DataGrid
https://material-ui.com/components/data-grid/rows/
Let me know.
Regards,
Emir

The fix was released in v4.0.0-alpha.10.
Reference: https://github.com/mui-org/material-ui-x/issues/571

It is indeed bug with DataGrid. You need to downgrade library to version: 4.0.0-alpha.8 or set it to "https://pkg.csb.dev/mui-org/material-ui-x/commit/02423225/#material-ui/data-grid"

Related

How to have a free width column based on the row width in the table?

and I have the following code:
return (
<Box sx={{ height: 400 }}>
<DataGrid columns={columns} rows={rows} />
</Box>
)
and I am having the table getting rendered as:
I want the column of the email to take the width of the widest row cell automatically, so I want the table to render as follows:
My colums and rows look simply as follows:
const columns = [ { field: "firstName" }, { field: "lastName" }, ...etc ]
const rows = [
{ firstName: "Camil Pasa Sokak", lastName: "In The Village", ...etc },
... etc
]
How to do it in MUI x (community table, the free one)?
I want the column of the email to take the width of the widest row cell automatically
please note: since the table is wide, it will automatically show you a scrollbar (x and y scrollbars). I want to keep this functionality, I want to keep these scrollbars (from the x and y) I don't want to disable them.
Here's a sandbox instnce:
https://codesandbox.io/s/strange-newton-z6pwj4?file=/src/App.js
Looking at the docs for the datatable component you are using, it's not super clear the best way to go about it. The crux of the problem is that this is a div + flexbox table and not a true html table. As such, cells within a single column are not really "bound" to each other the same way as a regular html table.
There is a page which addresses column dimensions, but I could not find a satisfactory solution there. I was particularly disappointed that maxWidth seems to do nothing. The closest I got was setting a fixed column width, but I don't think that's what you want:
const columns = [{
field: "email", width: 300,
}]
So then I moved on to their styling cells page, which allows you to have much more control over styling, but this still doesn't work because one flex cell does not affect the size of all flex cells in a column - each row has a different sized cell based on the size of the email address.
const columns = [{
field: "email", cellClassName: "foobar",
}]
<DataGrid columns={columns} rows={rows} sx={{
"& .foobar": {
maxWidth: "300px !important"
}
}} />
So, my best suggestion is to loop over the data, find the longest email address, and set the fixed width based on that. This kinda sucks, but I don't see another way to properly set dimensions for a flexbox-based table:
const longestEmail = rows.reduce((longest, row) => {
return row.email.length > longest.length ? row.email : longest
}, '');
const columns = [{
// play around with the multiplier until you find a suitable width
field: "email", width: longestEmail.length * 9,
}]
This is from the Documentation..Number Signature
<DataGrid
columns={[
{ field: 'username', colSpan: 2, hideable: false },
{
field: 'organization',
sortable: false,
filterable: false,
hideable: false,
},
{ field: 'age', hideable: false },
]}
rows={rows}
{...other}
/>
you can use colspan but it sets all cells in the column to span a given number of columns.
const columns = [{
field: "email",colSpan:2,
},]

React-Table display contents of array as individual elements inside a cell

I am trying to use react-table to visualise some data structured as below:
{
companyName: "Barclays Bank Plc",
tenancies: ["G.01 # Newbuilding"],
status: "Active",
accountNumber: "EX209302",
logo: "companylogo1",
},
{
companyName: "Boeing AerospaceLtd",
tenancies: ["G.01 # Newbuilding", "G.02 # Newbuilding"],
status: "Active",
accountNumber: "EX209302",
logo: "companylogo1",
},
My column definition (which doesn't work) looks something like this:
{
Header: "Tenancies",
accessor: "tenancies",
Cell: (tableProps) => (
<div>{tableProps.cell.value.forEach((item) => item)}</div>
),
},
What I am trying to do is display each array item within it's own HTML tags (such as a div) so I can visually style and seperate them within the table cell.
Can anyone point me in the right direction as to the best way to achieve this?
According to the API document, the Cell receives the table Instance and returns a valid JSX.
{
...
Cell: (tableInstance) => JSX
}
Since the tenancies array are available from tableInstance.row.original.tenancies, so you can change your tenancies column definition as follow:
{
Header: "Tenancies",
Cell: ({ row }) => {
return (
<div>
{row.original.tenancies.map((tenancy, i) => (
<div key={i}>{tenancy}</div>
))}
</div>
);
}
}
Here is the example:

Has column show property stopped working in latest react-table v7?

I have used the show property to show/hide columns in my table earlier and it has worked fine using react-table v7. However, recently I cannot get it to work any longer, since I've made a bunch of changes and my table is quite complex I'm not sure what caused it, possibly also an update of react-table itself (7.0.0-beta.12 to 7.0.0-rc.5).
Anyway, now I can't even get the most basic show example to work:
const columns = React.useMemo(
() => [
{
Header: "Info",
columns: [
{
Header: "Age",
accessor: "age",
show: false
},
{
Header: "Visits",
accessor: "visits"
}
]
}
],
[]);
https://codesandbox.io/s/react-table-hide-column-2g3js
Why is the 'age' column showing?
Edit
Digging into the changelog I now understand that column show/hide has indeed changed:
7.0.0-beta.28 Added the useColumnVisibility plugin as a core plugin along with several new instance and column-level methods to control
column visibility Added the "column-hiding" example
However, I still have not figured out how to apply the useColumnVisibility hook to a column in a similar way to how show used to work. The "column-hiding" example shows how to do it with checkboxes but does not help in my case (afaik).
I had a similar issue as I was using show. Instead of setting show in the column, set the initialState.hiddenColumns, here you can convert your existing show into the initial hidden columns:
useTable<T>(
{
columns,
data,
hiddenColumns: columns.filter(column => !column.show).map(column => column.id)
},
I couldn't use that as my columns are loaded dynamically (so the initial state was set to some columns that didn't exist, and was just set to an empty array) so I used:
React.useEffect(
() => {
setHiddenColumns(
columns.filter(column => !column.show).map(column => column.id)
);
},
[columns]
);
where setHiddenColumns is provided by useTable:
const {
headerGroups,
rows,
prepareRow,
state,
toggleRowSelected,
toggleAllRowsSelected,
setHiddenColumns
} = useTable<T>(
{
columns,
data,
getRowId,
...
This means if I changed the column props it would be reflected in the table.
I also use setHiddenColumns to show/hide columns. However, instead returning Header, I use id. My code:
...
setHiddenColumns,
flatColumns,
headerGroups,
state: { pageIndex, pageSize },
} = useTable({
columns,
data,
initialState: { pageIndex: 0 },
manualPagination: true,
pageCount: controlledPageCount,
},
useSortBy,
usePagination
);
React.useEffect(() => {
const hiddenColumns = flatColumns.filter((column: any) => !column.show).map((column: any)=> column.id);
setHiddenColumns(hiddenColumns); }, []);

dojo 1.8 data grid populated from query not rendering

I want to create datagrid which is populated based on the query made to server
the code i have is
require(["dojo/dom", "dojo/_base/array", "dojo/dom-construct", "dojo/domReady!", "dojox/grid/DataGrid", "dojo/data/ObjectStore"],
function (DataGrid, ObjectStore, dom) {
var formQuery;
require(["dojo/dom-form"], function (domForm) {
formQuery = domForm.toQuery("form-filter");
});
var query = url + '?' + formQuery;
console.log(query);
var myStore;
require(["dojo/store/JsonRest"], function (JsonRest) {
myStore = new JsonRest({target: query});
});
grid = new DataGrid({
store: dataStore = new ObjectStore({objectStore: myStore}),
structure: [
{name: "ID", field: "id", width: "25%"},
{name: "Task-predmet", field: "subject", width: "25%"},
{name: "Dodavatel", field: "contractorCompany", width: "10%"},
{name: "Stav", field: "status", width: "10%"},
{name: "Termin", field: "deadline", width: "10%"},
{name: "Vytvorene", field: "created", width: "10%"}
]
}, "result-table-contractor-tasks-filter"); // make sure you have a target HTML element with this id
grid.startup();
the query is
http://localhost:8080/path?deadlineFrom=2015-11-15&deadlineTill=2016-11-15&createdFrom=2015-11-15&createdTill=2016-11-15
and it returns this
{"code":200,"status":"success","data":[{"id":1,"contractorCompany":"Best","status":"OTV","deadline":"Nov 4, 2016","subject":"","created":"Nov 3, 2016 1:11:22 PM"},{"id":3,"contractorCompany":"Best","status":"OTV","deadline":"Nov 14, 2016","subject":"a","created":"Nov 14, 2016 2:37:15 PM"}]}
but the datagrid is not rendering and i have no idea why. can you please help me? i'm using dojo 1.8
Because dojox modules are experimental, and the grid is deprecated, might I recommend using SitePen's current dgrid? It is being actively developed, and has an accompanying library dstore that includes a 'Request' data store which is made for exactly this purpose.
Otherwise, if you're still interested in using the dojox/DataGrid, check out this article: https://www.sitepen.com/blog/2008/11/21/effective-use-of-jsonreststore-referencing-lazy-loading-and-more/

ExtJS4 grid grouping header renderer - How to specify?

Anyone know how to attach a renderer to a grid grouping header in ExtJS4? In ExtJS3 I have the following working code, which returns 'Past' if an event has been completed ('Y'), or 'Upcoming' if not completed:
function fmt_group_heading(groupVal) {
if (groupVal === 'Y') {
return 'Past';
} else {
return 'Upcoming';
}
}
// create the Grid
var fitGrid = new Ext.grid.GridPanel({
store: fitGroupingStore,
columns: [
{header: "ID", dataIndex: 'id', hidden: true },
{header: 'Event', width:320, dataIndex: 'event',
renderer:fmt_event_description},
{header: 'Events', dataIndex: 'completed', hidden: true,
renderer: fmt_group_heading }
],
stripeRows: true,
// config options for stateful behavior
stateful: true,
stateId: 'grid',
hideHeaders: true,
view: new Ext.grid.GroupingView({
groupRenderer: 'completed',
forceFit: true
})
});
ExtJS4 provides grid grouping but I'm not understanding how to change the output of the group text. The 'groupHeaderTpl' attribute of Ext.grid.feature.Grouping seems to only take the raw field value as read from the store.
this.groupingFeature = Ext.create('Ext.grid.feature.Grouping', {
groupHeaderTpl: 'Group: {completed}'
});
// create the Grid
this.fitnessGrid = new Ext.grid.Panel({
store: this.fitnessEventStore,
features: [this.groupingFeature],
// etc.......
try smth like this:
groupHeaderTpl:
'{[fmt_group_heading(values.name)]}
({rows.length}
Item{[values.rows.length > 1 ? "s" :
""]})'
The groupHeaderTpl requires you to use {name} when composing the template. It will only use the value provided by the groupField.
See the Docs.
Try this:
groupHeaderTpl: '{[values.rows[0].completed]}'

Resources