Autoclose='outside' doesn't work with multiple menu in react-bootstrap - reactjs

I have a dropdown with 2 possibles menus that can reach each others by clicking on some dropdown items. By adding autoClose='outside' I fixed the problem of untimely closing when clicking somewhere in the dropdown main menu. But since I have another menu, once it's showed, the first time I open it, the autoClose doesn't really work, instead, it's as if it was never set, close the whole dropdown, and when I reopen it, go in the secondary menu for the second, this 'bug' doesn't occur again on this menu, but occurs when I go back in the first one etc..
I suspect it's because autoClose only works on the current selected menu, in the example below it works with the main menu and does not in the secondary menu first then, as described above, when I reopen the dropdown it shows directly the secondary menu, works, and once I go back in the main menu, it doesn't.
This is basically the code I'm running.
import {Dropdown} from 'react-bootstrap';
import {useState} from 'react';
const Mydropdown = (props) => {
const [menu,setMenu] = useState('main');
return(
<>
<Dropdown autoClose='outside'>
{
menu=="main"
&&
(
<>
<Dropdown.Menu>
<Dropdown.Item onClick={()=>setMenu("secondary")}>
Secondary menu
</Dropdown.Item>
</Dropdown.Menu>
</>
)
}
{
menu=="secondary"
&&
(
<>
<Dropdown.Menu>
<Dropdown.Item onClick={()=>setMenu("main")}>
Secondary menu
</Dropdown.Item>
</Dropdown.Menu>
</>
)
}
</Dropdown>
</>
);
}

I'm not sure I'm following your requirements 100%, but this version should allow a single dropdown to optionally toggle contents (without auto-closing):
const Mydropdown = (props) => {
const [menu, setMenu] = useState("main");
return (
<Dropdown autoClose="outside">
<Dropdown.Toggle variant="primary">Dropdown Test</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item href="#">Menu Item</Dropdown.Item>
<Dropdown.Item href="#">Menu Item</Dropdown.Item>
<Dropdown.Item href="#">Menu Item</Dropdown.Item>
{menu == "main" && (
<Dropdown.Item onClick={() => setMenu("secondary")}>
Secondary menu
</Dropdown.Item>
)}
{menu == "secondary" && (
<Dropdown.Item onClick={() => setMenu("main")}>
Main menu
</Dropdown.Item>
)}
</Dropdown.Menu>
</Dropdown>
);
};
Working example available here: https://codepen.io/ablewhite/pen/BawdVpg

If I understand your question correctly you want a dropdown menu with another dropdown menu inside of it? The following code would acomplish that, I would suggest using autoClose={false) to prevent the menu from closing.
import { Dropdown } from "react-bootstrap"
import { useState } from "react"
const Mydropdown = (props) => {
const [menu, setMenu] = useState("main")
return (
<Dropdown autoClose={false}>
<Dropdown.Toggle>
Main Menu
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item onClick={() => setMenu("secondary")}>Action 1</Dropdown.Item>
{menu === "secondary" &&
<Dropdown autoClose={false}>
<Dropdown.Toggle>
Secondary
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item onClick={() => setMenu("main")}>Action 2</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
}
</Dropdown.Menu>
</Dropdown>
)
}
export default Mydropdown

Related

React. Headless UI Menu Items can't receive focus on keyboard navigation

I have a dropdown menu builth with Headless UI Menu component, but the menu links inside this dropdown are not getting focused on keyboard navigation.
my code goes something like so:
function Dropdown(parent, children) {
return (
<Menu as="div" className="Submenu">
{
({close}) => (
<>
<Menu.Button>
{ parent.label }
</Menu.Button>
<Menu.Items as="ul" className="subitems">
{
children.map(child => (
<Menu.Item as="li" className="subitem" key={ child.id }>
<Link href={ child.link }>
{ child.label }
</Link>
</Menu.Item>
))
}
</Menu.Items>
</>
)
}
</Menu>
);
}
The only thing getting the focus is the <ul></ul that wraps the items, but once I press tab the dropdown closes and the focus goes to the next item on the parent level menu.
The final html rendered is this:
I've tried to add tabIndex={0} to the tags, but the output stays the same.
I also tried to create a Link wrapper component ike suggested here, but it didn't work.

How to stop the toggle/show item in react-bootstrap Dropdown?

code:-
<td style={{ color: "white", width: "250px" }}>
<DropdownButton id="SelectFocus" title={playdata.ChannelName} tabIndex={-1}
onToggle={ontoggle}
menuVariant='dark'
>
{Channelname.map((val, id) => {
{
return (
<Fragment key={id}>
{removeRedundant([...val, playdata.ChannelName]).map((val1) => {
return (
<Dropdown.Item
onClick={(e) => { setPlayer(val1, playdata.idx, StoreIdx) }}
key={val1}>{val1}</Dropdown.Item>
)
})}
</Fragment>
)
}
})
}
</DropdownButton>
</td>
I am using react bootstrap for dropdown when I press down key button its automatically open the items/options how can I stop that?
i don't want item appear when I press the down key so how can I stop that in react js?
Please help...
When you use DropdownButton component, there is an additional div around the button. Use more low level Dropdown components to set tabIndex on button directly:
<Dropdown>
<Dropdown.Toggle tabIndex={-1}>Test</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item>Test 1</Dropdown.Item>
<Dropdown.Item>Test 2</Dropdown.Item>
<Dropdown.Item>Test 3</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
But keep in mind once you have focused the dropdown with click, you will get the same behaviour when pressing arrow down.
To prevent dropdown from toggling I believe you can use the onKeyDown event, but I wasn't able to get it work so far:
const handleKeyDown = (event) => {
if (event.key === "ArrowDown") {
event.preventDefault();
}
};

App function seems to re-execute and wipes out state (with React Bootstrap DropDown)

I have a very simple app for learning and playing with React.
It uses one Bootstrap Dropdown and two Bootstrap buttons.
The goal is to set a state variable from the item picked in the Dropdown component, and concatenate it into the text displayed for each of the two buttons. And that actually works for a split second, but then the page seems to reload, and it goes back to the default value ('BTC-USDT' in my sample). So I still don't understand the page load and events in React. Why is the page reloading? (I have a console.log("Start function App") which makes me believe that it is.)
Code:
import logo from './logo.svg';
import './App.css';
import React,{useState} from 'react';
import Button from 'react-bootstrap/Button';
import DropdownButton from 'react-bootstrap/DropdownButton';
import Dropdown from 'react-bootstrap/Dropdown';
import 'bootstrap/dist/css/bootstrap.min.css';
function App() {
console.log("Start function App")
const [getCoinPair,setCoinPair]=useState('BTC-USDT');
const handleSelectCoinFromDropdown=(e)=>{
console.log('Coin selected:');
console.log(e);
setCoinPair(e)
// alert('Coin Selected ' + e);
}
function buy() {
alert('Clicked Buy');
}
function sell() {
alert('Clicked Sell');
}
return (
<div>
<Dropdown onSelect={handleSelectCoinFromDropdown}>
<Dropdown.Toggle
variant="secondary btn-sm"
id="dropdown-basic">
Coin/Pair
</Dropdown.Toggle>
<Dropdown.Menu style={{backgroundColor:'#73a47'}}>
<Dropdown.Item href="BTC-USDT">BTC-USDT</Dropdown.Item>
<Dropdown.Item href="CRV-USDT">CRV-USDT</Dropdown.Item>
<Dropdown.Item href="LINK-USDT">LINK-USDT</Dropdown.Item>
<Dropdown.Item href="SUSHI-USDT">SUSHI-USDT</Dropdown.Item>
<Dropdown.Item href="YFI-USDT">YFI-USDT</Dropdown.Item>
<Dropdown.Item href="ZEN-USDT">ZEN-USDT</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
<br ></br>
<br ></br>
<Button variant='success' onClick={buy}>
Buy {getCoinPair}
</Button>
<Button variant='danger' onClick={sell}>
Sell {getCoinPair}
</Button>
</div>
);
}
export default App;
It is resetting because you are not pulling the correct data from the event.
Try this:
const handleSelectCoinFromDropdown=(e)=>{
setCoinPair(e.target.value)
}
The issue was with using href= on the Dropdown.Item's.
I was following first few models on this page: https://react-bootstrap.github.io/components/dropdowns/
They first examples on that page, not sure why, all use href=. But later on that page, they give an example with "eventKey=" instead of "href=".
I believe the href was going to a page, such as http://localhost:3000/SUSHI-USDT, which was causing the page to reload (not my intention).
<Dropdown.Menu style={{backgroundColor:'#73a47'}}>
<Dropdown.Item eventKey="BTC-USDT">BTC-USDT</Dropdown.Item>
<Dropdown.Item eventKey="CRV-USDT">CRV-USDT</Dropdown.Item>
<Dropdown.Item eventKey="LINK-USDT">LINK-USDT</Dropdown.Item>
<Dropdown.Item eventKey="SUSHI-USDT">SUSHI-USDT</Dropdown.Item>
<Dropdown.Item eventKey="YFI-USDT">YFI-USDT</Dropdown.Item>
<Dropdown.Item eventKey="ZEN-USDT">ZEN-USDT</Dropdown.Item>
</Dropdown.Menu>

Dropdownlist alternative in material UI of react

I am currently using simple-menu of material UI as shown in the codesandbox here. In my react app, I am displaying this menu in a primereact dialog.
However, my main requirement is to display a dropdown list in a dialog so that when a user selects something, it can be selected and I can do something based on that.
For example, if a user selects Car, I can see it selected. Also, I have some values associated with each entries.
For example, Company has value 0,Car has value 1 and Office has value 2.
So I am planning to have some buttons in the dialog so that after an item from the list is selected, and Ok button is selected, I can send the value associated with the selected item in a webservice call.
The closest I could find is simplelist:
https://material-ui.com/components/lists/#simple-list
But nothing close to Drowpdown list. Am I missing on something here?
More info:
The dialog looks like this:
And let's say, when I select an item, let's say, Car, it won't show Car but will display Open Menu which I am not looking for.
What I have achieved is when the dropdown is opened and some option is selected then users can see what they have selected and dropdown doesn't close when some option is selected and in the console you can see what option is selected by index number.
You can follow this code:
import React, { useState } from "react";
import Button from "#material-ui/core/Button";
import Menu from "#material-ui/core/Menu";
import MenuItem from "#material-ui/core/MenuItem";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles((theme) => ({
root: {
width: "100%",
maxWidth: 360,
backgroundColor: theme.palette.background.paper
}
}));
export default function SimpleMenu() {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const [visval, setVisval] = useState("Open Menu");
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
//console.log(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const classes = useStyles();
const [selectedIndex, setSelectedIndex] = React.useState();
const handleListItemClick = (event, index) => {
setSelectedIndex(index);
handleClose();
//console.log(index);
if (index === 0) {
setVisval("Company");
} else if (index === 1) {
setVisval("Car");
} else {
setVisval("Office");
}
};
return (
<div>
<Button
aria-controls="simple-menu"
aria-haspopup="true"
onClick={handleClick}
>
{visval}
</Button>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem
data-my-value={1}
selected={selectedIndex === 0}
onClick={(event) => handleListItemClick(event, 0)}
>
Company
</MenuItem>
<MenuItem
data-my-value={2}
selected={selectedIndex === 1}
onClick={(event) => handleListItemClick(event, 1)}
>
Car
</MenuItem>
<MenuItem
data-my-value={3}
selected={selectedIndex === 2}
onClick={(event) => handleListItemClick(event, 2)}
>
Office
</MenuItem>
</Menu>
</div>
);
}
You can checkout the updated and working codesandbox here
EDIT :
I have achieved what you asked i.e, the menu showing the three options should close when we select some option and the same should be visible in the place of Open Menu. But what I saw is that the code is no longer reusable and is becoming too large (I was aware of it).
If you want your code to be minimised then follow the bellow suggestion
SUGGESTION :
I saw that Material-ui's autocomplete just does the work with a clean code.
It gives you a set of options like a dropdown menu and when the user select's something the selected option is seen by the user.
Link to the Working Demo
You can migrate the same code into your dialog's content it will work fine.

React bootstrap default selected value for dropdown

I was using react-bootstrap library and I wanted to have default selected value.
I went through their docs and I wasn't able to find anything related to pass/set default value.
This is how I am currently using
const dropDownQuestion = (props) => {
const { options, upsideEmit, value } = props
return (
<DropdownButton
id="dropdown-basic-button"
onSelect={(eventKey) => upsideEmit(eventKey)}
>
{options.map((element) => (
<Dropdown.Item key={element.id}>{element.value}</Dropdown.Item>
))}
</DropdownButton>
)
}
Where value happens to be optional default Value. Can someone help me how to achieve this with react-bootstrap dropdown?
It depends on what do you mean by default value. If you mean value that appears on the dropdown button before the user touch it, you can simply insert it (hard-coded or by variable) as the text of the Dropdown.Toggle, for example:
<Dropdown.Toggle id="dropdown-basic">
Your "default value" here
</Dropdown.Toggle>
If by default value you mean the value of the dropdown's selected item before the user touch it, it's up to you, by choosing it in the data structure you use to set the values, for example:
var options = ["1", "2", "3", "4", "5"];
let chosenValue=options[0] // The "default Value"
function onSelect(eventKey, event) { // user can change the "default value"
chosenValue=eventKey;
.
.
.
}
<Dropdown onSelect={onSelect}>
<Dropdown.Toggle id="dropdown-basic" />
<Dropdown.Menu>
{options.map(option => (
<Dropdown.Item
eventKey={option}
key={option}>
{option}
</Dropdown.Item>
))}
</Dropdown.Menu>
</Dropdown>
You can use the active prop on the Dropdown.Item to highlight it, if that's what you mean?
A DropdownButton isn't designed as an input, so you can't have a "default value", each item in the menu is rendered as a button.

Resources