Ant design 4.20 new Menu item style - reactjs

Ant Design deprecated <Menu.Item> in 4.20.0, so I am converting it to a new format.
When I have the following code, how do I convert it into the new format?
<Menu>
<Menu.Item key="1" className={css.first} onClick={onFirst}>item 1</Menu.Item>
<Menu.Item key="2" className={css.second} onClick={onSecond}>item 2</Menu.Item>
</Menu>;

Ant Design v4.21.7 you can convert it like that
import React, { useState } from 'react';
import 'antd/dist/antd.css';
import './index.css';
import { Menu } from 'antd';
const App = () => {
const [current, setCurrent] = useState();
const onFirst = (e) => {
console.log('click 1', e);
setCurrent(e.key);
};
const onSecond = (e) => {
console.log('click 2', e);
setCurrent(e.key);
};
const items = [
{
label: 'Navigation One',
children: [
{
label: 'item 1',
onClick: onFirst,
key: '1',
className: 'first',
},
{
label: 'item 2',
onClick: onSecond,
key: '2',
className: 'second',
},
],
},
];
return <Menu selectedKeys={[current]} mode="horizontal" items={items} />;
};
export default App;

Related

How to implement AddAdiditions in React Sematic UI using Hooks?

I want to have a drop down in my application which allows the user to add an item to the dropdown. I am using React Sematic UI.
Sematic UI Dropdown ALlowAdditions
I am new to react hooks and I want to know how I can implement the onChange and onAddition function using hooks.
import React, { Component } from 'react'
import { Dropdown } from 'semantic-ui-react'
const options = [
{ key: 'English', text: 'English', value: 'English' },
{ key: 'French', text: 'French', value: 'French' },
{ key: 'Spanish', text: 'Spanish', value: 'Spanish' },
{ key: 'German', text: 'German', value: 'German' },
{ key: 'Chinese', text: 'Chinese', value: 'Chinese' },
]
class DropdownExampleAllowAdditions extends Component {
state = { options }
handleAddition = (e, { value }) => {
this.setState((prevState) => ({
options: [{ text: value, value }, ...prevState.options],
}))
}
handleChange = (e, { value }) => this.setState({ currentValue: value })
render() {
const { currentValue } = this.state
return (
<Dropdown
options={this.state.options}
placeholder='Choose Language'
search
selection
fluid
allowAdditions
value={currentValue}
onAddItem={this.handleAddition}
onChange={this.handleChange}
/>
)
}
}
export default DropdownExampleAllowAdditions
Any help would be greatly appreciated. Thanks in advance :)
import React, { useState } from "react";
import { Dropdown } from "semantic-ui-react";
const options = [
{ key: "English", text: "English", value: "English" },
{ key: "French", text: "French", value: "French" },
{ key: "Spanish", text: "Spanish", value: "Spanish" },
{ key: "German", text: "German", value: "German" },
{ key: "Chinese", text: "Chinese", value: "Chinese" }
];
const DropDownWithHooks = () => {
const [dropDownOptions, setDropDownOptions] = useState(options);
const [currentValue, setCurrentValue] = useState("");
const handleAddition = (e, { value }) => {
setDropDownOptions((prevOptions) => [
{ text: value, value },
...prevOptions
]);
};
const handleChange = (e, { value }) => setCurrentValue(value);
return (
<Dropdown
options={dropDownOptions}
placeholder="Choose Language"
search
selection
fluid
allowAdditions
value={currentValue}
onAddItem={handleAddition}
onChange={handleChange}
/>
);
};
export default DropDownWithHooks;
Working Sandbox

how to use icon in Ant-design/icons with V4

I have tried to make a menu, so i create a menuList to config the menu with getMenuNodes(), but Ant framework has been upgraded from v3 to v4 which the icon method has been changed. they are now using icon={<PieChartOutlined />} to instead of icon='PieChartOutlined', everything is working well, the icon area shows the word <PieChartOutlined />right now. i do not know why it happened, please help me to solve this problem.
left-navigation.js
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import logo from '../../assets/images/logo.png';
import './index.less';
import { Menu } from 'antd';
import { PieChartOutlined } from '#ant-design/icons';
import menuList from '../../config/menuConfig';
const { SubMenu } = Menu;
export default class LeftNav extends Component {
getMenuNodes = menuList => {
return menuList.map(item => {
if (!item.children) {
return (
<Menu.Item key={item.key} icon={item.icon}>
<Link to={item.key}>{item.title}</Link>
</Menu.Item>
);
} else {
return (
<SubMenu key={item.key} icon={item.icon} title={item.title}>
{this.getMenuNodes(item.children)}
</SubMenu>
);
}
});
};
render() {
return (
<div className="left-nav">
<Link to="./" className="left-nav-header">
<img src={logo} alt="" />
<h1>Backend System</h1>
</Link>
<Menu
mode="inline"
theme="dark"
>
{this.getMenuNodes(menuList)}
</Menu>
</div>
);
}
}
menuList.js
const menuList = [
{
title: 'Home',
key: '/home',
icon: '<PieChartOutlined />',
},
{
title: 'Item',
key: '/products',
icon: '<PieChartOutlined />',
children: [
{
title: 'Category Control',
key: '/category',
icon: '<PieChartOutlined />',
},
{
title: 'Product Control',
key: '/product',
icon: '<PieChartOutlined />',
},
],
},
{
title: 'User Control',
key: '/user',
icon: '<PieChartOutlined />',
},
{
title: 'Role Control',
key: '/role',
icon: '<PieChartOutlined />',
},
{
title: 'Diagram',
key: '/charts',
icon: '<PieChartOutlined />',
children: [
{
title: 'Bar',
key: '/charts/bar',
icon: '<PieChartOutlined />',
},
{
title: 'Line',
key: '/charts/line',
icon: '<PieChartOutlined />',
},
{
title: 'Pie',
key: '/charts/pie',
icon: '<PieChartOutlined />',
},
],
},
];
export default menuList;
You are passing a string of '<PieChartOutlined />', you need to pass the component directly.
import { PieChartOutlined } from '#ant-design/icons';
and:
{
title: 'Product Control',
key: '/product',
icon: <PieChartOutlined />,
},
You'll need to install ant-design/icons if you haven't already:
npm install --save #ant-design/icons
Since reason performance on the previous version, antd team was apply tree-shaking to use icon. More detail, you can check https://ant.design/docs/react/migration-v4

React.js: Customize sidebar menu based on API response

I'm trying to customize the sidebar navigation menu of my app based on a JSON response
The concept I'm trying to pattern my code to is using React Context and React Hooks
From my Header.js (which is my top navigation)
import {
useUserDispatch,
customizeSidebar
} from "../../context/UserContext";
var userDispatch = useUserDispatch();
useEffect(() => {
if( selectedProduct.trim() == "remittance" ){
setIsRemLabelHidden(true)
} else if( selectedProduct == "inward" ){
customizeSidebar(userDispatch, "91454020-C1AC-446C-A1CA-C68F6FDBB053", props.history)
setIsRemLabelHidden(false)
}
}, [selectedProduct]);
I trigger customizeSidebar function which is found in my UserContext.js
export {
UserProvider,
useUserState,
useUserDispatch,
customizeSidebar,
};
function customizeSidebar(dispatch, profileId, history){
ProfileMaintenanceService.retrieveProfileDetails(profileId)
.then((response) => {
console.log("customizeSidebar response.data ", response.data)
}).catch((err) => {
// check first if api is down
console.log("customizeSidebar - catch err.response.data >>> ", err.response.data)
})
}
As seen above, I can now get the JSON response in the then statement.
My question would be, how do I pass the JSON response, for instance I saved it in a state. How do I pass it to other component?
Specifically in my Sidebar.js
import React, { useState, useEffect } from "react";
import { Drawer, IconButton, List } from "#material-ui/core";
import {
SwapHoriz as SwapHorizIcon,
Inbox as InboxIcon,
PresentToAll as PresentToAllIcon,
Help as HelpIcon,
ListAlt as ListAltIcon,
Language as LanguageIcon,
Description as DescriptionIcon,
List as ListIcon,
Money as MoneyIcon,
Face as FaceIcon,
TransferWithinAStation as TransferWithinAStationIcon,
AttachMoney as AttachMoneyIcon,
PersonPinCircle as PersonPinCircleIcon,
Home as HomeIcon,
ArrowBack as ArrowBackIcon,
Edit as EditIcon
} from "#material-ui/icons";
import { useTheme } from "#material-ui/styles";
import { withRouter } from "react-router-dom";
import classNames from "classnames";
import useStyles from "./styles";
import SidebarLink from "./components/SidebarLink/SidebarLink";
import {
useLayoutState,
useLayoutDispatch,
toggleSidebar
} from "../../context/LayoutContext";
import Dot from "./components/Dot";
function Sidebar({ location }) {
var classes = useStyles();
var theme = useTheme();
var { isSidebarOpened } = useLayoutState();
var layoutDispatch = useLayoutDispatch();
var [isPermanent, setPermanent] = useState(true);
var structure = [
{ id: 0,
label: "Dashboard",
link: "/app/dashboard",
icon: <HomeIcon /> },
{
id: 1,
label: "Inward",
link: "/app/inward",
icon: <InboxIcon />,
children: [
{ label: "PESONet", link: "/app/inward/pesonet", icon: <Dot size="small" color="primary" /> },
{ label: "PESONet Inquiry", link: "/app/inward/pesonetinquiry", icon: <Dot size="small" color="primary" /> },
{ label: "PDDTS", link: "/app/inward/pddts", icon: <Dot size="small" color="primary" /> },
// { label: "PDDTS Inquiry", link: "/app/inward/pddtsinquiry" },
{ label: "SWIFT", link: "/app/inward/swift", icon: <Dot size="small" color="primary" /> },
// { label: "SWIFT Inquiry", link: "/app/inward/swiftinquiry" },
{ label: "Philpass", link: "/app/inward/philpass", icon: <Dot size="small" color="primary" /> },
],
},
// {
// id: 2,
// label: "Outward",
// link: "/app/outward",
// icon: <PresentToAllIcon />,
// children: [
// { label: "Inward", link: "/app/transfers/inward", icon: <InboxIcon /> },
// { label: "Outward", link: "/app/transfers/outward", icon: <PresentToAllIcon /> },
// ],
// },
{ id: 3, type: "divider" },
{
id: 4,
label: "Proof List",
link: "/app/prooflist",
icon: <ListAltIcon />,
children: [
{ label: "Proof Web", link: "/app/prooflist/web", icon: <LanguageIcon /> },
{ label: "Proof Others", link: "/app/prooflist/others", icon: <ListIcon /> },
],
},
{ id: 5, label: "Miscellaneous", link: "/app/misc", icon: <DescriptionIcon /> },
{
id: 6,
label: "RPS",
link: "/app/rps",
icon: <MoneyIcon />,
children: [
{ label: "Client Maintenance", link: "/app/rps/clientmaintenance", icon: <FaceIcon /> },
{ label: "Process SFTP", link: "/app/rps/sftp", icon: <TransferWithinAStationIcon /> },
{ label: "Process PESONet", link: "/app/rps/pesonet", icon: <AttachMoneyIcon /> },
{ label: "Override Enrollment", link: "/app/rps/overrideenrollment", icon: <PersonPinCircleIcon /> },
],
},
{ id: 7, label: "Message Converter", link: "/app/message", icon: <EditIcon /> },
];
useEffect(function() {
window.addEventListener("resize", handleWindowWidthChange);
handleWindowWidthChange();
return function cleanup() {
window.removeEventListener("resize", handleWindowWidthChange);
};
});
return (
<Drawer
variant={isPermanent ? "permanent" : "temporary"}
className={classNames(classes.drawer, {
[classes.drawerOpen]: isSidebarOpened,
[classes.drawerClose]: !isSidebarOpened,
})}
classes={{
paper: classNames({
[classes.drawerOpen]: isSidebarOpened,
[classes.drawerClose]: !isSidebarOpened,
}),
}}
open={isSidebarOpened}
>
<div className={classes.toolbar} />
<div className={classes.mobileBackButton}>
<IconButton onClick={() => toggleSidebar(layoutDispatch)}>
<ArrowBackIcon
classes={{
root: classNames(classes.headerIcon, classes.headerIconCollapse),
}}
/>
</IconButton>
</div>
<List className={classes.sidebarList}>
{structure.map(link => (
<SidebarLink
key={link.id}
location={location}
isSidebarOpened={isSidebarOpened}
{...link}
/>
))}
</List>
</Drawer>
);
function handleWindowWidthChange() {
var windowWidth = window.innerWidth;
var breakpointWidth = theme.breakpoints.values.md;
var isSmallScreen = windowWidth < breakpointWidth;
if (isSmallScreen && isPermanent) {
setPermanent(false);
} else if (!isSmallScreen && !isPermanent) {
setPermanent(true);
}
}
}
export default withRouter(Sidebar);
Also, should I save the json data on the state? Or on the context. If on the context, how?
Thanks in advance for those who would help.
Try this
use state. Make the customizeSidebar return the response, and call this kind of code in your SideBar component :
const [sideBar, setSideBar] = useState({})
useEffect(() => {
const sidebar = customizeSidebar()
setSideBar(sidebar)
}, [])
then below the code call your sidebar using the sideBar state, the sideBar will re-render with the new sidebar responded.
also maybe you want to put a loading animation while waiting for the sidebar result. I don't get the idea why you need to put it in context but the solution should works IMO.

How to add SrNo (#) column at first position at mui-datatable React.js

Created table using React and MUI-Datatables: need to add SrNo column at first, also need to add Delete and IsActive button.
import React, { useState, useEffect } from 'react';
import Grid from '#material-ui/core/Grid';
import Switch from '#material-ui/core/Switch';
import MUIDataTable from "mui-datatables";
export const Services = () => {
const [itemList, setItemList] = useState([]);
const [mainColumns, setMainColumns] = useState([]);
const selectData = async () => {
const response = await ServiceAPI(); // data from web wervice
var data = JSON.parse(response.data);
setItemList(data);
};
const createColumns = () => {
var columns = [];
// how to add Sr No column
columns.push(
{
label: 'ID',
name: 'service_id',
});
columns.push(
{
label: 'Name',
name: 'service_name',
});
setMainColumns(columns);
};
useEffect(() => {
createColumns();
selectData();
}, []);
return (
<>
<h3>Service</h3>
<Grid container >
<Grid item xs={12}>
<MUIDataTable
title={"Service"}
data={itemList}
columns={mainColumns}
className="table nowrap"
/>
</Grid>
</Grid>
</>
);
}
tried below code for active/deactivate, but OnChange() is run every time, which should call on only click event (also tried OnClick()):
columns.push(
{
label: 'Active',
name: 'is_active',
options: {
filter: false,
sort: false,
customBodyRender: (value, tableMeta, updateValue) => {
const serviceID = tableMeta.rowData[0];
return (
<Switch color="primary" checked={value} value={value} onChange={activate}/>
/>
);
}
}
});
Please check example. I have added serial number and delete button in this example.
import React from "react";
import ReactDOM from "react-dom";
import MUIDataTable from "mui-datatables";
import IconButton from "#material-ui/core/IconButton";
import Button from "#material-ui/core/Button";
export default class MuiDatatableSerial extends React.Component {
render() {
const columns = [
{name: "sl", label: "Serial No"},
{name: "name", label: "Name"},
{name: "title", label: "Title"},
{name: "location", label: "Location"},
{name: "age", label: "Age"},
{name: "salary", label: "Salary"},
{
name: "delete",
label: "",
options: {
filter: false,
sort: false,
customBodyRender: (value, tableMeta, updateValue) => {
return <Button
color="secondary"
onClick={(ev) =>
alert('deleted')
}> Delete
</Button>;
},
}
}
];
const data = [
{name: "Khabir Uddin", title: "Senior Software Engineer", location: "Dhaka", age: 38, salary: "$150,000"},
{name: "Gabby George", title: "Business Analyst", location: "Minneapolis", age: 30, salary: "$100,000"},
{name: "Aiden Lloyd", title: "Business Consultant", location: "Dallas", age: 55, salary: "$200,000"}
];
let newData = [];
data.map((item, index) => {
newData.push({sl: index + 1, ...item});
});
const options = {
selectableRows: "none",
onRowsSelect: (rowsSelected, allRows) => {
},
};
return (
<MUIDataTable
title={"ACME Employee list"}
data={newData}
columns={columns}
options={options}
/>
);
}
}

React-Select - clickable values with custom handler

Using react-select, I'd like to understand how I can get the events for when selected values (multi) are clicked.
I'm using react-select with the multi select functionality (https://react-select.com/home).
Works as a charm but I'd like to make the values clickable/toggleable to change color/state (not add/remove). In the end showing them in grey/color to indicate a marked state and using the underlying state for subsequent code.
Is there any way to achieve this and if so how?
You could pass in a custom MultiValueLabel or MultiValueContainer and add an onClick handler.
import React from "react";
import ReactDOM from "react-dom";
import Select, { components } from 'react-select';
const options = [
{value: '1', label: 'Item 1', isToggled: true},
{value: '2', label: 'Item 2', isToggled: false},
{value: '3', label: 'Item 3', isToggled: false},
{value: '4', label: 'Item 4', isToggled: false},
{value: '5', label: 'Item 5', isToggled: false},
{value: '6', label: 'Item 6', isToggled: false},
]
const ReactSelectStyles = () => ({
multiValueLabel: (styles, {data: { isToggled }}) => ({
...styles,
backgroundColor: isToggled ? 'hotpink' : null,
color: isToggled ? 'white' : null
}),
});
const handleMultiValueClick = (e, props) => {
e.stopPropagation();
e.preventDefault();
console.log('A multi value has been clicked', props);
const option = options.find(option => option.value === props.data.value);
option.isToggled = !option.isToggled
}
const MultiValueLabel = props => {
return (
<div onClick={(e) => handleMultiValueClick(e, props)}>
<components.MultiValueLabel {...props} />
</div>
);
};
function App() {
return (
<Select
closeMenuOnSelect={false}
components={{ MultiValueLabel }}
defaultValue={[options[0], options[2], options[4]]}
isMulti
options={options}
styles={ReactSelectStyles()}
/>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Working Example

Resources