Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IconMenu] Support MenuItem nested menuItems #3265

Merged
merged 1 commit into from
Feb 16, 2016
Merged

Conversation

tommrr
Copy link

@tommrr tommrr commented Feb 9, 2016

If nested menuItem is used in MenuItem they close instantaneously.

This is an example of the bug. http://imgur.com/g4M32q4

@mbrookes mbrookes added the PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI label Feb 9, 2016
@mbrookes
Copy link
Member

mbrookes commented Feb 9, 2016

@mbrookes mbrookes changed the title Fixed issue that meant that if submenu's are used in drop downs then … [IconMenu] Support MenuItem nested menuItems Feb 9, 2016
this.close(isKeyboard ? 'enter' : 'itemTap', isKeyboard);
}, this.props.touchTapCloseDelay);

if (this.props.onItemTouchTap > 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this line. That's not supposed to be a number.

    onItemTouchTap: React.PropTypes.func,

@tommrr
Copy link
Author

tommrr commented Feb 9, 2016

Try that, hopefully I haven't got the wrong object this time.

@mbrookes mbrookes added PR: Needs Review and removed PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI labels Feb 9, 2016

const descriptions = {
simple: 'Simple Icon Menus demonstrating some of the layouts possible using the `anchorOrigin` and `' +
'targetOrigin` properties.',
controlled: 'Two controlled examples, the first allowing a single selection, the second multiple selections.',
scrollable: 'The `maxHeight` property limits the height of the menu, above which it will be scrollable.',
nested: 'Example of nested menus within a icon menu.',
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"an Icon Menu" (or "an IconMenu") - I'm still never sure which, despite the fact I wrote all those descriptions. 😄

Icon Menu to refer to the feature, IconMenu to refer to the React component.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I think whenever we're mentioning another component we should use the component name with back ticks.

`IconMenu`

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you like me to change the description? To IconMenu then?

@mbrookes
Copy link
Member

mbrookes commented Feb 9, 2016

I'm wondering if this can be achieved without the extra prop? What is Menu / MenuItem doing for nested menus?

@tommrr
Copy link
Author

tommrr commented Feb 10, 2016

@mbrookes I'm not using an extra prop, the prop was already there and when you set it to less than 1 then with the original code the menu just disappears, which is useless if you have nested menus as the main menu disappears before you can click on the nested menu. In the project I am working on that uses this library we have a very deep context menu if we have it all in a one level drop down then it easily goes of the bottom of the screen, so using nested menus is a must.

iconButtonElement={<IconButton><MoreVertIcon/></IconButton>}
anchorOrigin={{horizontal: 'left', vertical: 'top'}}
targetOrigin={{horizontal: 'left', vertical: 'top'}}
touchTapCloseDelay={-1}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about touchTapCloseDelay={0}?
However, that sounds like a hack.

@oliviertassinari
Copy link
Member

I'm wondering if this can be achieved without the extra prop?

I agree, I think that we should be checking for a menuItems property on the MenuItem component clicked. If it's not there, we close the menu. child.props.menuItems

@oliviertassinari oliviertassinari added PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI and removed PR: Needs Review labels Feb 10, 2016
@tommrr
Copy link
Author

tommrr commented Feb 10, 2016

Updated with the feedback. Let me know if anything else needs changing.

@mbrookes mbrookes added PR: Needs Review and removed PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI labels Feb 10, 2016
@@ -13,12 +13,15 @@ import IconMenuExampleControlled from './ExampleControlled';
import iconMenuExampleControlledCode from '!raw!./ExampleControlled';
import IconMenuExampleScrollable from './ExampleScrollable';
import iconMenuExampleScrollableCode from '!raw!./ExampleScrollable';
import IconMenuExampleNested from './ExampleNestedDrop';
import iconMenuExampleNestedCode from '!raw!./ExampleNestedDrop';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you call the file ExampleNested.jsx please.

@oliviertassinari
Copy link
Member

@tomrosier I haven't tested it, but that looks great from a diff point of view 👍.

<MenuItem primaryText="Propercase" />,
]}
/>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about add a MenuItem without a menuItems property in this example?

@oliviertassinari
Copy link
Member

@tomrosier That looks good to me. Could you squash down the commits and have a look at my comment?


const descriptions = {
simple: 'Simple Icon Menus demonstrating some of the layouts possible using the `anchorOrigin` and `' +
'targetOrigin` properties.',
controlled: 'Two controlled examples, the first allowing a single selection, the second multiple selections.',
scrollable: 'The `maxHeight` property limits the height of the menu, above which it will be scrollable.',
nested: 'Example of nested menus within a IconMenu.',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"an IconMenu"

@oliviertassinari oliviertassinari added PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI and removed PR: Needs Review labels Feb 12, 2016
…they would close instantaneously

Made my changes comply with the lint standards

Changed onItemTouchTap to touchTapCloseDelay, as accidentally chose wrong one.

added the ability for the icon-menu to detect if any of the sub items contain submenus

Updated with changes from @oliviertassinari and @mbrookes

Renamed a file

updated the examples, and corrected spelling
@oliviertassinari oliviertassinari added PR: Review Accepted and removed PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI labels Feb 16, 2016
@oliviertassinari
Copy link
Member

That looks good to me 👍.

@alitaheri
Copy link
Member

This is great 👍 Thanks a lot 😁

alitaheri added a commit that referenced this pull request Feb 16, 2016
[IconMenu] Support MenuItem nested menuItems
@alitaheri alitaheri merged commit 9987d3c into mui:master Feb 16, 2016
@Dreculah
Copy link

I have a very similar requirement, and using the 'children' prop of menuItems almost works for my leftNav menu items.

Using redux, I am passing in an Immutable Map (and ignoring the React warning). As you can see, it does make the indented children. However, it puts them ABOVE the primaryText vs below them.

Is there something I'm doing wrong, or (1) we should have a config to specify children location or (2) children should be below primaryText?

Thanks!

render() {
        let me = this,
            getSubItems = (subItems) => {
                if(!subItems) return null;
                return subItems.map(function(subItem, key) {
                    let subName = subItem.get('name'),
                        subKey  = 'sub' + key;
                    if(EnableConsoleLog) console.log('subName: ', subName);
                    return (<MenuItem
                        key={subKey}
                        primaryText={subName}
                        onTouchTap={me.handleToggle.bind(me)}
                    />)
                });
        },
        menuItems = me.props.menuItems.map(function(menuItem, key) {
            let name     = menuItem.get('name'),
                subItems = menuItem.get('subItems');
                if(EnableConsoleLog) console.log('name: ', name);
                return (<MenuItem
                    key={key}
                    primaryText={name}
                    onTouchTap={me.handleToggle.bind(me)}
                    insetChildren={true}
                    children={getSubItems(subItems)}
                />)
        });
        return (
            <div id="my-page-container">
                <LeftNav
                    ref="leftNav"
                    docked={false}
                    open={me.state.open}
                    children={menuItems}
                />
                <AppBar title='React Reflux Material UI' onLeftIconButtonTouchTap={me.handleToggle.bind(me)}/>
                <div style={styles.container}>
                    I am the app component with mui
                </div>
            </div>
        )
    }
store.dispatch({
    type: 'SET_STATE',
    state: {
        uiState: {
            aKey: 'aValue'
        },
        domainState: {
            menuItems: {
                lastViewed: {
                    name: 'Recent Items',
                    subItems: {
                        salesOrders: {
                            name: 'Pythons'
                        },
                        creditMemos: {
                            name: 'Penguins'
                        }
                    }
                },
                dashboard: {
                    name: 'Dashboard'
                },
                sales: {
                    name: 'Animals',
                    subItems: {
                        customers: {
                            name: 'Puppies'
                        },
                        salesOrders: {
                            name: 'Parakeets'
                        },
                        shipments: {
                            name: 'Pythons'
                        },
                        customerInvoices: {
                            name: 'Parrots'
                        },
                        creditMemos: {
                            name: 'Peacocks'
                        },
                        customerReceipts: {
                            name: 'Penguins'
                        }
                    }
                },
                financials: {
                    name: 'Mordant'
                },
                allPages: {
                    name: 'All Pages'
                }
            }
        }
    }
});

nestedmenuitems

@alitaheri
Copy link
Member

@Dreculah Are you using OrderedMap? because Map doesn't guarantee order.

@Dreculah
Copy link

@alitaheri This logic is not contingent on sorting, since there will only be subMenu items produced produced and added as children for an object with subItems. I also see the expected console.log messages and as you can see below the DOM is built with the expected nesting (pythons and penguins as subItems of Recent Items), but not rendered as such...

React devTools:
zdom

actual DOM:
actualdom

@alitaheri
Copy link
Member

Please try toJS() if that fixes it it's react, if not it's us O.o

@Dreculah
Copy link

I switched from a hash map to array so I could use toJS() for map iteration, and I still see exactly the same problem.

Unfortunately, I don't know the material-ui & react source code yet, so I can't spot the problem straight away. It is odd that the React DOM would have the expected structure, but not the browser DOM.

@alitaheri
Copy link
Member

Yeah exactly! This is really surprising to me! Can you reproduce this using a very simple array?

@Dreculah
Copy link

The array is pretty simple now (please see below).

Maybe its a React bug?

menuItems: [
                {
                    name: 'Recent Items',
                    subItems: [
                        {
                            name: 'Pythons'
                        },
                        {
                            name: 'Penguins'
                        }
                    ]
                },
                {
                    name: 'Dashboard'
                },
                {
                    name: 'Animals',
                    subItems: [
                        {
                            name: 'Puppies'
                        },
                        {
                            name: 'Parakeets'
                        },
                        {
                            name: 'Pythons'
                        },
                        {
                            name: 'Parrots'
                        },
                        {
                            name: 'Peacocks'
                        },
                        {
                            name: 'Penguins'
                        }
                    ]
                },
                {
                    name: 'Mordant'
                },
                {
                    name: 'All Pages'
                }
            ]

@alitaheri
Copy link
Member

it cannot be a bug with react. and I can't reproduce this on my end. any chance you can write a small failing test so we can make it pass? I looked at the code, if there is anything wrong it's not related to this PR anyway as it,s not where the logic actually happens. So it's going to be hard to fix. A failing test will be the fastest way to squeeze out this bug. And make sure it will never happen again 👍

@Dreculah
Copy link

OK, thanks! I've asked one of my teammates to have a go at this.

@alitaheri
Copy link
Member

That's great news. thank you and your teammate for looking into this 👍 👍

@Dreculah
Copy link

Thank you for material-ui!

@alitaheri
Copy link
Member

You should thank callemall and @hai-cea, I'm just a simple collaborator 😅

But I'm really glad this project is helping your company 👍 👍

@cfkenandy
Copy link

Hi @alitaheri , I’m working with @Dreculah . I have created 2 failing test cases for the
nested menu items. You can find the project and the testcase at: nestedMenuItems.zip
After you npm install, you should be able to run the test using ’npm run test’ . ‘test/Main_test.jsx’ contains the test cases. Let me know if you need more information or any help with this.

@alitaheri
Copy link
Member

@cfkenandy Wow that's awesome thank you 👍 any chance you can turn that zip into a PR so that others can check it out with ease? That would be awesome. 😍

@cfkenandy
Copy link

@alitaheri , You mean I should create a branch from https://github.com/callemall/material-ui/ and then create a PR?

@alitaheri
Copy link
Member

@cfkenandy You should fork this repository, then create a branch on your fork, then update your branch with the failing tests and then submit a PR wanting to merge that branch from your fork onto the master branch of this repository.

@mbrookes
Copy link
Member

mbrookes commented Mar 2, 2016

@cfkenandy
Copy link

Thanks! Am on it.

@cfkenandy
Copy link

@alitaheri Hope I got this right. #3573

@alitaheri
Copy link
Member

@cfkenandy Yes you did. thank you 👍 👍

@zannager zannager added the component: menu This is the name of the generic UI component, not the React module! label Mar 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: menu This is the name of the generic UI component, not the React module!
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants