Unable to update state from onClick event of MDBDatable row in React - javascript

I'm using MDBReact for the creation of a simple data table that has some rows and setMe and getMe buttons. onClick of setMe button I wish to set a value to the cropName state value and onClick of getMe button, I wish to retrieve the update state value.
The problem is that I only receive emptystring values every time inside the getMe function even after updating the state.
I have tried the following code, but unfortunately, it does not seem to update the state value. I only get an emptystring when the getMe button is clicked.
import React, { useState } from 'react';
import { render } from 'react-dom';
import { MDBDataTable } from 'mdbreact';
import './style.css';
import '#fortawesome/fontawesome-free/css/all.min.css';
import 'bootstrap-css-only/css/bootstrap.min.css';
import 'mdbreact/dist/css/mdb.css';
function App() {
const [cropName, setCropName] = useState('');
const [data, setData] = useState([]);
function setMe(e) {
console.log(setCropName('Hello'));
}
function getMe(e) {
console.log(cropName);
}
function loadTable() {
setData({
columns: [
{
label: 'Action',
field: 'radio',
sort: 'asc',
width: 150,
},
{
label: 'Position',
field: 'position',
sort: 'asc',
width: 270,
},
{
label: 'Office',
field: 'office',
sort: 'asc',
width: 200,
},
{
label: 'Age',
field: 'age',
sort: 'asc',
width: 100,
},
{
label: 'Start date',
field: 'date',
sort: 'asc',
width: 150,
},
{
label: 'Salary',
field: 'salary',
sort: 'asc',
width: 100,
},
],
rows: [
{
radio: (
<div className="field-input pt-2">
Click this
<button id="asdfsdasafsdf" onClick={setMe}>
set me!
</button>
<button id="asdfsdasafsdf" onClick={getMe}>
get me!
</button>
</div>
),
position: 'System Architect',
office: 'Edinburgh',
age: '61',
date: '2011/04/25',
salary: '$320',
},
{
name: 'Garrett Winters',
position: 'Accountant',
office: 'Tokyo',
age: '63',
date: '2011/07/25',
salary: '$170',
},
],
});
}
return (
<div>
<MDBDataTable striped bordered hover data={data} />
<button onClick={loadTable}>Load Table</button>
</div>
);
}
render(<App />, document.getElementById('root'));
Here the live demo of my implementation.

It looks like the state updates are not available to the functions fired from the table row event. I got my way around it by using useEffect statement and setting the dependency as the property that gets modified by the table row event.
import React, { useState, useEffect } from 'react';
import { render } from 'react-dom';
import { MDBDataTable } from 'mdbreact';
import './style.css';
import '#fortawesome/fontawesome-free/css/all.min.css';
import 'bootstrap-css-only/css/bootstrap.min.css';
import 'mdbreact/dist/css/mdb.css';
function App() {
const [cropName, setCropName] = useState('');
const [data, setData] = useState([]);
useEffect(()=>{
console.log('Crop changed')
}, [cropName])
function setMe(e) {
setCropName('Hello ID: '+Math.random());
}
function getMe(e) {
console.log(cropName);
}
function loadTable() {
setData({
columns: [
{
label: 'Action',
field: 'radio',
sort: 'asc',
width: 150,
},
{
label: 'Position',
field: 'position',
sort: 'asc',
width: 270,
},
{
label: 'Office',
field: 'office',
sort: 'asc',
width: 200,
},
{
label: 'Age',
field: 'age',
sort: 'asc',
width: 100,
},
{
label: 'Start date',
field: 'date',
sort: 'asc',
width: 150,
},
{
label: 'Salary',
field: 'salary',
sort: 'asc',
width: 100,
},
],
rows: [
{
radio: (
<div className="field-input pt-2">
Click this
<button id="asdfsdasafsdf" onClick={setMe}>
set me!
</button>
<button id="asdfsdasafsdf" onClick={getMe}>
get me!
</button>
</div>
),
position: 'System Architect',
office: 'Edinburgh',
age: '61',
date: '2011/04/25',
salary: '$320',
},
{
name: 'Garrett Winters',
position: 'Accountant',
office: 'Tokyo',
age: '63',
date: '2011/07/25',
salary: '$170',
},
],
});
}
return (
<div>
<MDBDataTable striped bordered hover data={data} />
<button onClick={loadTable}>Load Table</button>
{cropName}
</div>
);
}
render(<App />, document.getElementById('root'));
Demo

Related

MUI DataGrid layout issues using React

Been trying to get MUI DataGrid to work for a few hours now, but for some reason the styling is placing the pagination information at the top of the table, on top of the column headers.
Maybe its something stupid I'm doing. I have tried a really simple version to illustrate my issues. Hope someone can please help me. BTW I use v5+ of MUI and DataGrid. React is v17+
import React, { FC } from "react";
import { DataGrid, GridRowModel } from "#mui/x-data-grid";
import { GridColDef } from "#mui/x-data-grid";
export const DataGridTest: FC = () => {
const paginationSize = 20;
const columns: GridColDef[] = [
{ field: "username", headerName: "Username", flex: 1, sortable: false, filterable: false },
{ field: "first_name", headerName: "First Name", flex: 1, sortable: false, filterable: false },
{ field: "last_name", headerName: "Last Name", flex: 1, sortable: false, filterable: false },
{ field: "email", headerName: "Email", flex: 1, sortable: false, filterable: false },
{ field: "phone", headerName: "Phone", flex: 1, sortable: false, filterable: false },
];
const rows: GridRowModel[] = [
{
id: 1,
username: "Tony",
first_name: "Tony",
last_name: "Ballony",
email: "Tony#test.com",
phone: "0754512222",
},
{
id: 2,
username: "Joe",
first_name: "Joeseph",
last_name: "Willson",
email: "joe#test.com",
phone: "0754512333",
},
];
return (
<div>
<DataGrid rows={rows} columns={columns} pageSize={paginationSize} />
</div>
);
};
The output looks like this.
So you can see that the pagination section that should be shown below the table data is instead positioned at the top of the page. In fact the border that should be around the data is also moved to the top. I hope someone can help me out here.
You have to specify the height of DataGrid, like:
//// Your code ////
return (
<div>
<DataGrid
style={{ height: "700px" }}
rows={rows}
columns={columns}
pageSize={paginationSize} />
</div>
);
};
You can use stylesheets instead of inline styles ofc. It's just an example.

Display empty table/datagrid with empty lines in Material UI

I'm trying to display an empty table (ie with no data to display), with a predefined height but with a set of empty lines.
By default, the table is displayed with no lines (its background is empty).
I would like to display empty lines. Even, if the number of rows is lower than the maximum number of allowed rows in a page, I would like to complete the display with empty lines.
I tried at least a dirty solution by adding manually an empty line, but even like this the result is not as exptected as the line is squashed and not well displayed. Cf attached image:
Below is the code of my component:
export default function MyComponent() {
const classes = useStyles();
const columns: GridColumns = [
{
field: 'data1',
headerName: 'DATA 1',
width: 130,
headerClassName: 'data--header',
cellClassName: 'data--cell',
},
{
field: 'data2',
headerName: 'DATA 2',
width: 130,
headerClassName: 'data--header',
cellClassName: 'data--cell',
},
{
field: 'data3',
headerName: 'DATA 3',
width: 130,
headerClassName: 'data--header',
cellClassName: 'data--cell',
},
{
field: 'data4',
headerName: 'DATA 4',
width: 130,
headerClassName: 'data--header',
cellClassName: 'data--cell',
},
{
field: 'data5',
headerName: 'DATA 5',
width: 130,
headerClassName: 'data--header',
cellClassName: 'data--cell',
},
{
field: 'data6',
headerName: 'DATA 6',
width: 130,
headerClassName: 'data--header',
cellClassName: 'data--cell',
},
];
const rows = [
{ id: "0", data1: "AAA", data2: "BBB", data3: "CCC", data4:"DDD", data5:"EEE", data6: "FFF" },
];
for(var i=1; i<10 ; i++) {
rows.push({id: i, data1: "", data2: "", data3: "", data4:"", data5:"", data6: ""})
}
return (
<div className={classes.root} style={{ height: 300, width: 700 }}>
<DataGrid disableColumnMenu hideFooter rowCount="10"rows={rows} columns={columns} rowHeight="30" />
</div>
);
}
Can anybody give my a hint to move on this task ? I'm a bit stuck (and if there is a solution without the manual creation of empty lines it would even be better :-)).
Thank you!

Need keyboard accessibility(tab+enter) on AntD sorter

In antDesign Table, sorter produces the default caret-up and caret-down icons.
As a requirement,
I need keyboard access using tabIndex="0" on the caret-up and on the caret-down icons for navigation.
And onKeyPress of Enter on caret-up/caret-down icons, I need them to getSorted.
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Table } from 'antd';
const columns = [
{
title: 'Chinese Score',
dataIndex: 'chinese',
sorter: {
compare: (a, b) => a.chinese - b.chinese,
multiple: 3,
},
},
{
title: 'Math Score',
dataIndex: 'math',
sorter: {
compare: (a, b) => a.math - b.math,
multiple: 2,
},
},
{
title: 'English Score',
dataIndex: 'english',
sorter: {
compare: (a, b) => a.english - b.english,
multiple: 1,
},
},
];
const data = [
{
key: '1',
name: 'John Brown',
chinese: 98,
math: 60,
english: 70,
},
{
key: '2',
name: 'Jim Green',
chinese: 98,
math: 66,
english: 89,
},
{
key: '3',
name: 'Joe Black',
chinese: 98,
math: 90,
english: 70,
},
{
key: '4',
name: 'Jim Red',
chinese: 88,
math: 99,
english: 89,
},
];
function onChange(pagination, filters, sorter, extra) {
console.log('params', pagination, filters, sorter, extra);
}
ReactDOM.render(<Table columns={columns} dataSource={data} onChange={onChange} />, document.getElementById('container'));
Added picture of AntD

Building a dashboard with fluent-ui in React and the cards and table appear at bottom of screen when they're not supposed to

I am following a tutorial to build a dashboard using fluentui in React, and am going to customise it and change it afterwards. However I have followed the tutorial exactly and got no errors but for some reason the cards and table appear at bottom of screen, not looking like how they are styled and the table has no data in it.
My code is exactly the same as the tutorial found here: https://www.youtube.com/watch?v=P9s6dsdu_9c. I will post a screenshot below of how mine looks atm and all relevant code below that.
code:
App.js
import React from 'react';
import { BrowserRouter as Router} from 'react-router-dom';
import './App.css';
import 'office-ui-fabric-react/dist/css/fabric.css';
import Chart3 from './Components/Chart/Chart3';
import Jumbo from './Components/Jumbotron/Jumbotron';
import Footer from './Components/Footer/Footer';
import Header from './Components/Navbar/Navbar';
import Navigation from './Navigation/Navigation';
import CardsSection from './Components/Cards/Card';
import Table from './Components/Table/Table';
function App() {
return (
<div className="ms-grid" dir="ltr">
<div className="ms-grid-row">
<div className="ms-grid-col ms-sm1 ms-xl1">
<Navigation />
</div>
<div className="ms-Grid-col ms-sm11 ms-xl11 main-element">
<div className="ms-Grid-row">
<CardsSection />
</div>
<div className="ms-Grid-row">
<Table />
</div>
</div>
</div>
</div>
);
}
export default App;
Navigation.js
import React from 'react';
import {Nav, initializeIcons} from '#fluentui/react';
const Links = [
{
links: [
{
name: 'Dashboard',
url: '/',
key: 'key1',
iconProps: {
iconName: 'News',
styles: {
root: {
fontSize: 20,
color: '#106ebe'
}
}
}
},
{
name: 'Settings',
url: '/',
key: 'key2',
iconProps: {
iconName: 'SwitcherStartEnd',
styles: {
root: {
fontSize: 20,
color: '#106ebe'
}
}
}
},
{
name: 'Charts',
url: '/',
key: 'key3',
iconProps: {
iconName: 'StackedLineChart',
styles: {
root: {
fontSize: 20,
color: '#106ebe'
}
}
}
}
]
}
]
//Styling for the navigation
const navigationStyles = {
root: {
height: '100vh',
boxSizing: 'border-box',
border: '1px solid',
overFlowY: 'auto',
paddingTop: '10vh'
}
}
const Navigation = () => {
initializeIcons(); //initalizing so we can see icons when we use them
return (
<Nav
groups={Links}
selectedKey="key1"
styles={navigationStyles}
/>
)
}
export default Navigation;
Card.js
import React from 'react';
import { Card } from '#uifabric/react-cards';
import { Text, initializeIcons} from '#fluentui/react';
import 'office-ui-fabric-react/dist/css/fabric.css';
const container = {
display: 'flex',
justifyContent: 'center',
margin: '10vh 0'
}
const icon = {
fontSize: 24,
padding: 15,
verticalAlign: 'middle',
paddingLeft: 0,
color: '#0078d4'
}
const styles = {
cardStyles: {
root: {
backgroundColor: 'white',
padding: 20,
borderTop: '5px solid #0078d4',
width: '90%',
maxWidth: '90%',
margin: 'auto'
}
},
header: {
root: {
fontSize: 20,
fontWeight: 'bold',
}
},
amount: {
root: {
fontSize: 26,
paddingBottom: 20,
paddingTop: 30,
}
},
amount: {
root: {
fontSize: 16,
fontWeight: 'bold',
color: '#0078d4'
}
}
}
const cards = [
{
title: 'current balance',
amount: '21',
icon: 'Money',
percentage: '2.3',
},
{
title: 'current expenses',
amount: '215',
icon: 'PaymrntCard',
percentage: '2.3',
},
{
title: 'current income',
amount: '21',
icon: 'Savings',
percentage: '2.3',
},
]
const CardsSection= () => {
initializeIcons();//initailizing icons so can be used
return (
<div style={container}>
{cards.map((card) => (
<div className="s-Grid-col ms-sm3 ms-xl3">
<Card styles={styles.cardStyle}>
<Card.Section>
<Card.Item>
<i style={icon} className={`ms-Icon ms-Icon--${card.icon}`} aria-hidden="true"></i>
<Text styles={styles.header}>{card.title}</Text>
</Card.Item>
<Card.Item>
<Text styles={styles.amount}>{card.amount}</Text>
</Card.Item>
<Card.Item>
<Text styles={styles.percentage}>{card.percentage}%</Text>
</Card.Item>
</Card.Section>
</Card>
</div>
))}
</div>
)
}
export default CardsSection;
Table.js
import React from 'react';
import { DetailsList } from '#fluentui/react';
import { mergeStyleSets } from 'office-ui-fabric-react/lib/Styling';
import 'office-ui-fabric-react/dist/css/fabric.css';
const operations = [
{
from: '0000 0284 7529 304304',
to: '0000 9876 9876 5678 4123',
amount: '1.343',
date: '20-05-2020'
},
{
from: '0000 0284 7529 304304',
to: '0000 9876 9876 5678 4123',
amount: '1.343',
date: '20-05-2020'
},
{
from: '0000 0284 7529 304304',
to: '0000 9876 9876 5678 4123',
amount: '1.343',
date: '20-05-2020'
},
{
from: '0000 0284 7529 304304',
to: '0000 9876 9876 5678 4123',
amount: '1.343',
date: '20-05-2020'
},
{
from: '0000 0284 7529 304304',
to: '0000 9876 9876 5678 4123',
amount: '1.343',
date: '20-05-2020'
}
]
const columns = [
{ key: 'column1', name: 'From', fieldName:'From', minWidth: 100, maxWidth: 300, isResizable: true },
{ key: 'column2', name: 'To', fieldName:'To', minWidth: 100, maxWidth: 300, isResizable: true },
{ key: 'column3', name: 'Amount', fieldName:'Amount', minWidth: 100, maxWidth: 300, isResizable: true },
{ key: 'column4', name: 'Date', fieldName:'Date', minWidth: 100, maxWidth: 300, isResizable: true },
]
const classNames = mergeStyleSets({
teble: {
margin: 'auto'
}
});;
const Table = () => {
return (
<div data-is-scrollable={true}>
<div className={`s-Grid-col ms-sm9 ms-xl9 ${classNames.table}`}>
<DetailsList
items={operations}
columns={columns}
selectionMode={0}
/>
</div>
</div>
)
}
export default Table
In Table.js, there is a typo in the className. It has to be ms-Grid-col and not s-Grid-col

Getting pagination to work with React Komposer

I'm using Meteor 1.3.4.1, kurounin:pagination 1.0.9, and react-komposer 1.8.0 (npm package).
So here's my code for instantiating the pagination within composer function:
function composer(props, onData) {
console.log('loading pages');
const pagination = new Meteor.Pagination(UfcFighters);
if( pagination.ready() ) {
console.log('ready');
const fighters = {
columns: [
{ width: '5%', label: '', className: '' },
{ width: '20%', label: 'Name', className: 'text-center' },
{ width: '20%', label: 'Wins/Losses/Draws', className: 'text-center' },
{ width: '20%', label: 'Weight Class', className: 'text-center' },
{ width: '10%', label: 'Status', className: 'text-center' },
{ width: '10%', label: 'Rank', className: 'text-center' },
],
data: pagination.getPage(),
};
onData(null, { fighters, pagination });
}
};
Is this the proper use for React Komposer? I noticed that the Pagination would constantly load the subscription and never be ready to present the data. The console output would say 'loading pages' repeatedly, but it never says 'ready'.
Any advice would be appreciated.
Looks pretty good to me, I think you just need to return if the pagination is not ready.
function composer(props, onData) {
const pagination = new Meteor.Pagination(UfcFighters);
if(!pagination.ready()) { return; }
const fighters = {
columns: [
{ width: '5%', label: '', className: '' },
{ width: '20%', label: 'Name', className: 'text-center' },
{ width: '20%', label: 'Wins/Losses/Draws', className: 'text-center' },
{ width: '20%', label: 'Weight Class', className: 'text-center' },
{ width: '10%', label: 'Status', className: 'text-center' },
{ width: '10%', label: 'Rank', className: 'text-center' },
],
data: pagination.getPage(),
};
onData(null, { fighters, pagination });
};
Got an answer via the project maintainer of kurounin:pagination and here's my updated code which is confirmed to work with react komposer:
const pagination = new Meteor.Pagination(UfcFighters, {
sort: { id: 1 }
});
function composer(props, onData) {
const fighterDocs = pagination.getPage();
if( pagination.ready() ) {
const fighters = {
columns: [
{ width: '5%', label: '', className: '' },
{ width: '20%', label: 'Name', className: 'text-center' },
{ width: '20%', label: 'Wins/Losses/Draws', className: 'text-center' },
{ width: '20%', label: 'Weight Class', className: 'text-center' },
{ width: '10%', label: 'Status', className: 'text-center' },
{ width: '10%', label: 'Rank', className: 'text-center' },
],
data: fighterDocs,
};
onData(null, { fighters, pagination });
}
};
export default composeWithTracker(composer)(FightersList);
I moved the pagination instance to outside of the composer function because it was constantly instantiating new Paginations and bogging down the app. Now it's running smoothly.
Hope this helps someone else.

Categories