How to make a react bootstrap dropdown with panelgroups - reactjs

I am trying to make a dropdown where each menuitem will have submenuitems
as
Drodown(select)
1. List item(header)
Litem-1(subheader)
Litem-2(subheader)
2. Header-2(header)
Litem-2-1(subheader)
Litem-2-2(subheader)
I am using react bootstrap dropdown to achieve this
where each menuitem would have a panelgroup of items as Litem-1 and Litem-2
So When i click on select the dropdown should open up, but when i click on individual headers(which are not expanded by default), should expand and should not close the dropdown and when clicked on subheaders dropdown has to be closed
I have tried using open option of dropdown ,using this i am trying to control the visibility of the dropdown i could achieve the same for headers when i try to do the same i could not achieve because the event is bubbling up till the parent and dropdown remains open , i also tried to use stopPropagation but looks like menuitem is not respecting it not sure why it is the case
I tried to solve this as this
https://codepen.io/anon/pen/WONMGd
can some one please comment if this approach is right and also why cannot I use event.stopPropagation and prevent default here
Thanks

To use panels in the way you sort of want them to you have to set the accordion prop on your panel to be true. Check out the code below:
<Dropdown.Menu className="Groups" bsRole="menu">
<MenuItem onClick={this.menuItemClickedThatShouldntCloseDropdown.bind(this)}>
<PanelGroup activeKey="1" accordion activeKey={this.state.activeKey}>
<Panel header="header1" eventKey='1'>
<span onClick={this.menuItemShouldCloseDropDown.bind(this)}>Content-1</span>
</Panel>
<Panel header="header2" eventKey='2'>
<span onClick={this.menuItemShouldCloseDropDown.bind(this)}>content=2</span>
</Panel>
</PanelGroup>
</MenuItem>
<MenuItem onClick={this.menuItemClickedThatShouldntCloseDropdown}>
hi
</MenuItem>
</Dropdown.Menu>
</Dropdown>
and add this to your class definition:
handleSelect(activeKey) {
this.setState({ activeKey })
}
This seems to solve at least one of your problems. Id recommend tearing out the other pseudo-state this._forceOpen logic to see what you really need.

Related

Antd DatePicker: Input in extra footer can't change, select or focus

I am working with antd Datepicker and I want custom Datepicker component look like this.
Now, I use prop renderExtraFooter to add custom footer. My input time in footer is other lib (react-datepicker). My problem is here. I can't change, select, focus any input render in extra footer. I want my input time can use (select, change, focus, ...) but I don't know how to do this.
Here is my trying code: https://codesandbox.io/s/antd-custom-antd-12hgbd
I try .blur() antd Datepicker input but still not work.
Any can help me or tell me a lib to custom DatePicker look like picture. Thank for your help.
The only solution is kind of an hack & you will need to handle open & closing of the panel via a state variable.
<DatePicker
showToday={false}
open={true}
renderExtraFooter={() => (
<div onMouseDown={(e) => e.stopPropagation()}>
<input />
</div>
)}
/>
If you remove the open={true} prop, the input will focus but the picker will close immediately. You need to control the visibility of the panel with the open property.

Ant design Collapse is not working with Map

I'm using collapse using Ant-Design put inside the Collapse tag if I put Map for panel, It's not working can someone suggest me the solution. Without Map It work. But using Map it's not.
Here is the Code:
<Collapse
defaultActiveKey={["1"]}
accordion
expandIcon={(props) => customExpandIcon(props)}
ghost
>
{JSON.map((assesment, index) => (
<div>
<Panel index header="This is panel header 1" key="1">
<p>Header1</p>
</Panel>
</div>
))}
</Collapse>
There seems to be a few problems I would like to point out that should be corrected.
It is not JSON.map but some list of objects (maybe assesments.map).
I think Panel has to be a direct decendent of Collapse so it should not be in a div tag.
Key property should be index so that not all panels have key 1
Here you have a example using map
https://codesandbox.io/s/mystifying-microservice-tuef7?file=/index.js
Please ask any questions if this did not answer your question.

React.js Map Array style for a unique id and each button disabled

I need each question button when it is clicked to be disabled. I would also like to style each question button. I already looked for several answers to this problem but I found nothing. As I don't know much about React in this case, should I use useEffect or children.props? If you have any solution please let me know.
Demo
Your buttons' state is already available for each button, you just need to use state and disable button.
{/* Question buttons */}
{buttons.map((button) => (
<button key={button.id} disabled={button.clicked} onClick={() => buttonClickHandler(button.id)}>
{button.label}
</button>
))}
About styling buttons individually, you can create a className for each button and style buttons depending on that:
<button className={'button-' + button.id}>
and now from css apply color:
.button-01 { background: pink; }
The second approach could be that you create styles for each button inside the state, and consume it from there.
<button style={button.style}>

React widgets combobox; how to clear input or prevent selection

I'm using the combobox from React Widgets as a search UI component.
I've put in a custom render item so that when you click a search result in the dropdown, you navigate to the relevant page.
However when you select a result, the name of the selected item goes into the text input, which isn't what a user will expect when they select a search result. I think they'd expect the search term to remain, or perhaps the input to be cleared.
I like the Combobox component and haven't found another UI widget that would do what I want, so I'd like to find a solution.
Is there some way to override the selection behaviour so that clicking a list item doesn't select it? I've tried setting the 'onSelect' property but this doesn't suppress the default selection behaviour, it just adds extra functionality.
Alternatively is there a way to manually set the selection to null? The docs don't seem to show anything. I tried getting the input node's value manually to '' with reactDOM, but the value didn't change. I would guess that the component controls it.
I've wrapped the Combobox in a functional component:
function Search(props) {
...
const onSelect = (value) => {
const node = ReactDOM.findDOMNode(Search._combobox);
const input = node.getElementsByTagName('input')[0];
input.value = '';
}
return (
<Combobox
ref={(c) => Search._combobox = c}
onSelect={onSelect}
textField="name"
valueField="_id"
/>
);
}
If I set the value prop of the Combobox then it is impossible to type into it.
Any suggestions? Thank you.
The solution I found is to create my own search controls using an input and a button, and hide the native input and button with display: none. "componentDidUpdate" detects when new search results arrive and opens the dropdown to show them.
There is a manually-added 'show more...' entry at the end of search results. Clicking this increases the search limit for that group. That's the main reason I wanted to avoid showing the clicked result in the text input. The custom input is not affected by the user's selection, it always shows the search term.
My search component now looks something like this:
<div className="search">
<div className="search-controls">
<Input
onChange={this.onChangeInput}
type="text"
/>
<Button
onClick={this.toggleOpen}
title="toggle results"
>
<FontAwesomeIcon icon={['fas', 'search']} style={{ 'color': iconColors.default }} size="1x" />
</Button>
</div>
<Combobox
busy={isSearching}
data={searchResults}
onChange={() => {}}
open={open}
onSelect={this.onSelect}
textField="name"
valueField="_id"
/>
</div>

Keyboard navigation (accessibility) with ant design- SubMenu

I need to make my site accessible. I'm using ant-design Menu, and the Menu.Submenu is not keyboard accessible, i believe. By adding tabindex i can tab to the submenu, but clicking ENTER nothing happens- the submenu doesn't open, i have no way of programatically openning it.
Under handleKeyPress i'm able to register the ENTER click event on the submenu title but i cant get the submenu to open and show the items. Is there functionality for that?
Perhaps there's a way and i'm missing something?
<Menu.SubMenu onKeyPress={(event) => this.handleKeyPress(event,
"EditYourProfileSubMenu")} onTitleClick={()=>{alert('title clicked')}}
tabIndex={0} title="Edit Your Profile" style={{ color: 'white' }}>
It would be very nice to have an entire Menu which is keyboard accessible, including navigation with arrows and automatic enter click triggers click events.
But i'll also be happy with a way to programatically open ant design SubMenu.
I'm still waiting for a better solution, maybe someone will reply to
https://github.com/ant-design/ant-design/issues/14356
I found a meantime hacky solution for this- using Menu's openKeys prop(see https://ant.design/components/menu/). It gets an array of submenu keys to determine which are open. So using onKeyDown i listened to these events and added/removed the right submenu key from the array (using State, of course).
<Menu
openKeys={this.controller.getMainMenuOpenKeys()}
...>
...
<Menu.SubMenu key={"EditYourProfileSubMenu"}
onKeyDown={(event) => this.handleKeyPress(event, "EditYourProfileSubMenu", true)}
onTitleClick={() => {
this.controller.setMainMenuOpenKeys(["EditYourProfileSubMenu"]) }} //sets the state which openKeys listens to
tabIndex={0}
title="Edit Your Profile" style={{ color: 'white' }}>
...
</Menu.SubMenu>
</Menu>
Adding openKeys field to menu messes with the mouse click flow, so i had to add onTitleClick and add the key to openKeys there also.

Resources