Using a Prop to populate an array - React useState - javascript

I have 3 dropdowns, each which controls state. When this dropdown is selected it will set the target and send it to redux. For example.
const [interviewStep1, setinterviewStep1] = useState('Phone Screening')
const [interviewStep2, setinterviewStep2] = useState('Formal Interview')
const [interviewStep3, setinterviewStep3] = useState('Reference Check')
This is sent to redux in this manner.
<Dropdown_Content>
{interviewStageSelection.map((option) => (
<Dropdown_Item
key={option}
onClick={(e) => {
setinterviewStep1(option)
setisActive(!isActive)
console.log(interviewStep1)
setisActive(false)
updateInterview1(dispatch, option)
}}
>
<Typography variant="subtitle5" color="black" sx={{ "&:hover": { color: "white" } }}>{option}</Typography>
</Dropdown_Item>
))}
</Dropdown_Content>
I then pass this state as props into my next component.
export default function JobPostInterviewVerticalStepper(interviewStep1, interviewStep2, interviewStep3)
this does come through, but then I want to display in my array. How do I use these props?
const steps = [
{
label: 'Phone Screening',
//I WANT A interviewStep1 here!
},
{
label: 'Formal Interview',
},
{
label: 'Reference Check',
},
{
label: 'Offer',
},
];

Related

How can I do dynamic badge on React CoreUI?

I have a problem with a badge on Core UI. I have a Sidebar and one of the elements is Chat. When a new message comes, the badge must show new message. But the old developer have written different ways and I can not change it. I cannot find anything for this.
My codes
Sidebar elements
const _nav = [
{
_tag: "CSidebarNavItem",
name: "Chat",
to: "/chat",
filter: "feedbacks",
icon: "cil-speech",
badge: {
color: "info",
text: "NEW MESSAGE",
},
},
]
My React component
import navigation from "./_nav";
const [filteredNav, setFilteredNav] = useState([]);
const [chatBadge, setChatBadge] = useState(false);
const handleChatBadge = () => {
setChatBadge(true)
}
// it is a sidebar element for user-role
useLayoutEffect(() => {
allwedMenu().then((res) => {
const arr = [navigation[0]];
res.data.items.forEach((element) => {
arr.push(element.name);
});
setFilteredNav(navigation.filter((item) => arr.includes(item.filter)));
});
}, []);
<CSidebarNav>
<CCreateElement
items={filteredNav}
components={{
CSidebarNavDivider,
CSidebarNavDropdown,
CSidebarNavItem,
CSidebarNavTitle,
}}
/>
</CSidebarNav>
I need the badge to show when chatBadge is true. But I don't know how can I write this.
You can only add a condition to show the badge when chatBadge is true.
Based on the Value of ChatBadge, you can use the property of the Component CSideBarNavItem to display the badge and pass the colour and text properties.
Here's the updated code:
<CSidebarNav>
<CCreateElement
items={filteredNav}
components={{
CSidebarNavDivider,
CSidebarNavDropdown,
CSidebarNavItem,
CSidebarNavTitle,
}}
/>
{filteredNav.map((item, index) => (
<CSidebarNavItem
key={index}
name={item.name}
to={item.to}
icon={item.icon}
badge={
item.name === "Chat" && chatBadge
? { color: "info", text: "NEW MESSAGE" }
: null
}
/>
))}
</CSidebarNav>
Hope it helps.

Getting content of currently active Text component wrapped inside popover of antd

I am using antd components for my react app. I have a Text component wrapped inside of Popover component. Now in my case this Popover is applied to one particular column of table, i.e. every row-element in that column has a Popover component rendered for it upon mouse hovering.
title: "Name",
dataIndex: "name",
key: "name-key",
sortType: "string",
sortDirections: ["descend", "ascend"],
sorter: (a, b) => a.name.length - b.name.length,
render: (text, record) => (
<Popover>
<Text onMouseOver={handleOnMouseOverCommitId}> {name} </Text>
</Popover>
)
I want to get hold of the row-element's value, the one contained by the above Text component whenever I hover over it. In this case the value denoted by {name} above.
I tried getting it with e.target.value via onMouseOver event, but it returned undefined.
I think I get the reason behind it, because the event.target returns an html node of type <span>.
With a normal div element e.target.value has worked in the past for me. But doing the same thing with a predefined component like antd's Text seems a bit trickier.
Just to elaborate, the Popover has two buttons and based on which button user clicks, I need to render some other components, something like an overlay component.
But in order to do that I would also need to get hold of the text value which originally triggered the Popover.
Below is the code(most of the things removed for preciseness).
record.name is what I ultimately need to capture.
<Popover
content={
<>
<Space>
<Button onClick={showSomeOverlayPaneForName}>
{"View Details for record.name"}
</Button>
<Button href={"https://abc.xyz.com/" + record.role}>
{"View Role Details"}
</Button>
</Space>
</>
}
trigger={"hover"}
>
<Text style={{"color": blue.primary}} copyable={true} onMouseOver={handleOnMouseOverName}>{record.name}</Text>
</Popover>
The handleOnMouseOverName function(which doesn't work anyway) :
const handleOnMouseOverName = (e) => {
//console.log("e.target.value :--- ", e.target.value);
setCurrentActiveName(e.target.value)
}
And once my currentActiveName variable is set(via useState), I use that value inside my function showSomeOverlayPaneForName
const showSomeOverlayPaneForName = (e) => {
axios
.get(
`some-url`,
{
params: {name: currentActiveName}
}
)
.then((response) => {
setData(response.data);
}).catch(reason => {
//xyz
});
}
You need to pass on the record of the enclosing render function to the handleOnMouseOverName function.
Check the following example
import React from 'react';
import 'antd/dist/antd.css';
import './index.css';
import { Space, Table, Button, Popover } from 'antd';
const App = () => {
const data = [
{
key: '1',
name: 'John Brown',
address: 'New York No. 1 Lake Park',
role: 'admin',
},
{
key: '2',
name: 'Jim Green',
address: 'London No. 1 Lake Park',
role: 'user',
},
{
key: '3',
name: 'Joe Black',
address: 'Sidney No. 1 Lake Park',
role: 'manager',
},
];
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
render: (name, record) => {
const content = (
<>
<Space>
<Button
onClick={() => {
viewDetail(record);
}}
>
{'View Details for ' + record.name}
</Button>
<Button href={'https://abc.xyz.com/' + record.role}>
{'View Role Details'}
</Button>
</Space>
</>
);
return (
<>
<Popover content={content} title="Details">
<div
onMouseOver={() => {
handleOnMouseOverName(record);
}}
>
{name}
</div>
</Popover>
</>
);
},
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
];
const handleOnMouseOverName = (record) => {
console.log(record);
};
const viewDetail = (record) => {
console.log(record);
};
return <Table columns={columns} dataSource={data} />;
};
export default App;
Output:
I hope this helps.
From antd docs: https://ant.design/components/popover/#header
Apparently you're supposed to render the <Popover/> with a content={content}-prop
For example
const content = <div>Content to render under title</div>
const App = () => {
const value = "Text to hover";
return (
<Popover content={content} title="Title">
<Text>{value}</Text>
</Popover>
)
}

React MUI Multiple Select with Checkboxes not Check marking Initial Selected Options

I am still new in React and MUI, so please spare my life. I am learning to build Multiple Select Options with Checkboxes and I have populated the Dropdown Options from an Array.
I also have set up the initial/default state options. The initial/default state options (Nintendo & XBoX) are showing up in the main Input Select Field but unfortunately not being checked marked in the Dropdown Checkboxes, such as in the screenshot below.
Screenshot 1
What I'm trying to achieve is to be like this (all the selected options (Nintendo & XBoX) from the default state is showing on the checkboxes at initial page load):
Screenshot 2
This is my Live Demo coding in https://stackblitz.com/edit/react-rahqrq?file=demo.js
I'm confused, I can tick all the other option checkboxes in the dropdown except the default Initial Options from the State. It's unclickable and unchangeable, I have no idea why. Any tips and clues are greatly appreciated, Thanks in advance, please pardon my poor Grammar and Best Regards.
import * as React from 'react';
import OutlinedInput from '#mui/material/OutlinedInput';
import InputLabel from '#mui/material/InputLabel';
import MenuItem from '#mui/material/MenuItem';
import FormControl from '#mui/material/FormControl';
import ListItemText from '#mui/material/ListItemText';
import Select from '#mui/material/Select';
import Checkbox from '#mui/material/Checkbox';
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
};
const variants = [
{
id: 3,
name: 'Voucher',
},
{
id: 1,
name: 'Top Up',
},
{
id: 2,
name: 'Game Key',
},
{
id: 12,
name: 'Other',
},
{
id: 11,
name: 'Nintendo',
},
{
id: 10,
name: 'Xbox',
},
];
export default function MultipleSelectCheckmarks() {
const [variantName, setVariantName] = React.useState([{
id: 11,
name: 'Nintendo',
},{
id: 10,
name: 'Xbox'
},]);
const handleChange = (event) => {
const {
target: { value },
} = event;
const preventDuplicate = value.filter((v, i, a) => a.findIndex((t) => t.id === v.id) === i);
setVariantName(
// On autofill we get a the stringified value.
typeof preventDuplicate === 'string' ? preventDuplicate.split(',') : preventDuplicate
);
};
return (
<div>
<FormControl sx={{ m: 1, width: 300 }}>
<InputLabel id="demo-multiple-checkbox-label">Tag</InputLabel>
<Select
labelId="demo-multiple-checkbox-label"
id="demo-multiple-checkbox"
multiple
value={variantName}
onChange={handleChange}
input={<OutlinedInput label="Tag" />}
renderValue={(selected) => selected.map((x) => x.name).join(', ')}
MenuProps={MenuProps}
>
{variants.map((variant) => (
<MenuItem key={variant.id} value={variant}>
<Checkbox checked={variantName.indexOf(variant) > -1} />
<ListItemText primary={variant.name} />
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
You need to findIndex of each item in the initial list to make them checked.
Try like below
{
variants.map(variant => (
<MenuItem key={variant.id} value={variant}>
<Checkbox
checked={
variantName.findIndex(item => item.id === variant.id) >= 0
}
/>
<ListItemText primary={variant.name} />
</MenuItem>
));
}
Code sandbox => https://stackblitz.com/edit/react-rahqrq-sd2m2b?file=demo.js

Filter unique option values with Autocomplete component from Material UI

I want Autocomplete from Material UI to list in the drop-down only unique option values from a property of the objects in my list of objects.
In the example below, the drop-down renders a list with the values ['Color1', 'Color2', 'Color1', 'Color2'], however I want it to render only unique values, like ['Color1', 'Color2'].
Here is the list of objects:
options = [
{
id: 1,
name: 'Name1',
color: 'Color1'
},
{
id: 1,
name: 'Name2',
color: 'Color2'
},
{
id: 1,
name: 'Name3',
color: 'Color1'
},
{
id: 1,
name: 'Name4',
color: 'Color2'
},
]
And here is the Autocomplete complete component:
<Autocomplete
freeSolo
value={initialTasting}
options={options}
getOptionLabel={option => option.color}
filterOptions={(options, state) => options}
onChange={(e, value) => {setFieldValue('color', value.color)}}
renderInput={params => (
<TextField
{...params}
label={'Color'}
variant='outlined'
margin='dense'
fullWidth
/>
)}
/>
I left the rest of the code out, since it's too long. It uses Formik, Yup, has children components so on.
I guess I can achieve the result I'm looking for using the prop filterOptions, however, I can't make it. I'm too new to JavaScript..!
Thanks in advance.
What do you think about updating your options array like this?..
function getUniqueListBy(arr, key) {
return [...new Map(arr.map(item => [item[key], item])).values()]
}
const optionsUnique = getUniqueListBy(options, 'color');
...and then pass optionsUnique to the options parameter from <Autocomplete /> component

How to clear Multiselect Dropdown in Semantic UI React using a button?

I have a Semantic UI React Multiselect Dropdown inside a React functional component and want to have buttons inside the menu, as such (still need to center them...)
How can I clear the selected values using the 'Clear' button?
I am able to clear the selection using the 'x' icon, but that's built into the component.
<Dropdown
search
multiple
selection
clearable
closeOnSelectionChange={false}
options={filterInitialSuggestions()}
className='selectDropdown'
header={dropdownButtons()}
/>
const dropdownButtons = () => {
return (
<div>
<Button positive size='mini'>
Save
</Button>
<Button grey size='mini' onClick={() => console.log('I want to reset the multi select dropdown')}>
Clear
</Button>
<Divider />
</div>
);
};
'Save' and 'Clear' buttons with React useState(). In Reactjs you don't need to use DOM queryselector.
https://codesandbox.io/s/white-leftpad-q6re3?file=/src/Fun.jsx
import React, { Component } from 'react';
import { Dropdown } from 'semantic-ui-react';
const options = [
{ key: 1, text: 'Choice 1', value: 1 },
{ key: 2, text: 'Choice 2', value: 2 },
{ key: 3, text: 'Choice 3', value: 3 },
{ key: 4, text: 'Choice 4', value: 4 },
{ key: 5, text: 'Choice 5', value: 5 },
{ key: 6, text: 'Choice 6', value: 6 },
]
class Example extends Component {
state = {
dropval: []
}
onDropChange = (e, { value }) => {
this.setState(
(prevState) => { return { ...prevState, dropval: value } },
// () => console.log(this.state)
)
}
render() {
return (
<div>
<Dropdown
search
multiple
selection
clearable
closeOnSelectionChange={false}
options={options}
className='selectDropdown'
onChange={this.onDropChange}
value={this.state.dropval}
style={{ width: 300 }}
/>
</div>
);
}
}
export default Example;
I figured out how to solve this issue. I'm not sure if this is the best way, but it seems to work decently.
const dropdownButtons = () => {
return (
<>
<div className='dropdown-saveButton'>
<Button
positive
size='mini'
onClick={() => {
saveValues();
}}
>
Save
</Button>
<Button size='mini' onClick={clearDropdown}>
Clear
</Button>
</div>
<Divider inverted />
</>
);
};
const clearDropdown = e => {
var element = dropdownRef.current.querySelector('[aria-selected="true"]');
if (element) {
dropdownRef.current.querySelector('.clear')?.click();
}
};
<Dropdown
multiple
selection
fluid
clearable
header={dropdownButtons} />

Categories

Resources