Search code examples
javascriptreactjsdropdown

Submenus are closing the dropdown on click


I installed react-multilevel-dropdown component to create a menu with submenus. It is displaying well, but the submenus are appearing only when i hover/mouseover the parent item and i wish it could display it on click the item too, so the submenu wouldn't hide when the mouse is not over the item. I created functions to show it when i click the item and it opens ok, but the dropdown is closing... I tryed to add e.stopPropagation but it did not prevent the dropdown to close.

That is how the component is now:

const StyledSubmenu = styled(Dropdown.Submenu)`
    display: ${props => (props.open ? "block" : "none")};
    margin-right: 2.5%;
    margin-top: 2.5%;
`;

function toggleSubmenu(e) {
    e.preventDefault();
    e.stopPropagation();
    setSubmenuOpen(!submenuOpen);
    if(submenuOpen2 === true){
        setSubmenuOpen2(!submenuOpen2);
    }
}

function toggleSubMenu2(e){
    e.preventDefault();
    e.stopPropagation();
    setSubmenuOpen2(!submenuOpen2);
    if(submenuOpen === true){
        setSubmenuOpen(!submenuOpen);
    }
}

The return where i display the component:

<StyledDropdown title={<i className="fa fa-sm fa-bars"></i>}>
            <StyledItem onClick={(e) => toggleSubmenu(e)}>
                <i className='fa fa-sm fa-arrow-left me-2'></i>Cadastro
                <StyledSubmenu open={submenuOpen}>
                    <StyledItem onClick={(e) => navigate('/estoque')}> Produtos </StyledItem>
                    <StyledItem onClick={(e) => navigate('/grp-consultar')}> Grupos </StyledItem>
                    <StyledItem onClick={(e) => navigate('/mar-consultar')}> Marcas  </StyledItem>
                    <StyledItem onClick={(e) => navigate('/loc-consultar')}> Localizações</StyledItem>
                    <StyledItem onClick={(e) => navigate('/uni-consultar')}> Unidades </StyledItem>
                    <StyledItem onClick={(e) => navigate('/cat-consultar')}> Categorias </StyledItem>
                    <StyledItem onClick={(e) => navigate('/tgr-consultar')}> Tipos de Grade </StyledItem>
                </StyledSubmenu>
            </StyledItem>
            <StyledItem onClick={(e) => toggleSubMenu2(e)}>
                <i className='fa fa-sm fa-arrow-left me-2'></i> Movimento
                <StyledSubmenu open={submenuOpen2}>
                    <StyledItem onClick={(e) => navigate('/sub-grupo-1')}> Movimento do Produto </StyledItem>
                    <StyledItem onClick={(e) => navigate('/sub-grupo-2')}> Controle de Produção </StyledItem>
                    <StyledItem onClick={(e) => navigate('/sub-grupo-3')}> Balanço de Estoque </StyledItem>
                    <StyledItem onClick={(e) => navigate('/sub-grupo-4')}> Acerto de Estoque </StyledItem>
                </StyledSubmenu>
            </StyledItem>
        </StyledDropdown>

How can i avoid the StyledDropdown to close when i click in the Item with submenu? I saw the other similar questions here, but all of them were not a multilevel menu.

EDIT:

i made a video of my screen showing the problem. You can notice that it closes my dropdown when i click in the item and when i open it again, the submenu is open (its correct, it should be opened, but without closing the dropdown before).

https://drive.google.com/file/d/1TOyL37bbCPcSYYw_aSpT18XUB_XDT4aB/view?usp=sharing


Solution

  • I found a way using primereact to fix the click and styledcomponents to let it more similar to the old menu:

    const menu = useRef(null);
    
    const items = [
        {
            label: 'Cadastros',
            icon: 'pi pi-fw pi-arrow-left',
            items: [
                {
                    label: 'Grupos',
                    command: () => navigate('/grp-consultar') 
                },
                {
                    label: 'Marcas',
                    command: () => navigate('/mar-consultar') 
                },
                {
                    label: 'Localizações',
                    command: () => navigate('/loc-consultar') 
                },
                {
                    label: 'Unidades',
                    command: () => navigate('/uni-consultar') 
                },
                {
                    label: 'Categorias',
                    command: () => navigate('/cat-consultar') 
                },
                {
                    label: 'Tipos de Grade',
                    command: () => navigate('/tgr-consultar') 
                }
            ]
        },
        {
            label: 'Movimentos',
            icon: 'pi pi-fw pi-arrow-left',
            items: [
                {
                    label: 'Movimento de Produto',
                    command: () => navigate('/sub-grupo-1') 
                },
                {
                    label: 'Controle de Produção',
                    command: () => navigate('/sub-grupo-2') 
                },
                {
                    label: 'Balanço de Estoque',
                    command: () => navigate('/sub-grupo-3') 
                },
                {
                    label: 'Acerto de Estoque',
                    command: () => navigate('/sub-grupo-4') 
                }
            ]
        }
    ];
    
    const StyledTiered = styled(TieredMenu)`
        background-color: var(--cor5);
        padding-top: 10px;
        padding-bottom: 10px;
        padding-left: none !important;
    
        .p-tieredmenu-submenu-icon {
            display: none; // Esconde o sinal '>'
        }
    `;
    

    then i render it like that:

    <React.StrictMode>
                <PrimeReactProvider>
                    <StyledTiered model={items} popup ref={menu} breakpoint="767px" />
                    {/* <Button label='Menu' onClick={(e) => menu.current.toggle(e)}> </Button> */}
                    <div className="btn btn-sm dropdown-titulo"  role="button"  onClick={(e) => menu.current.toggle(e)}> 
                        <i className="fa fa-lg fa-bars" id="icon-dropdown-titulo"></i> 
                    </div>
                </PrimeReactProvider>
            </React.StrictMode>
    

    i needed ti add some other styles in my css file and use !important to replace the component's original style, but i'll not post it here cause it is not important to resolve the problem, it is just design.

    So, if you want to open dropdown menu's submenus with clicks instead mouseover, use primereact!!!