Notice: The Monaca & Onsen UI Community Forum is shutting down.

For Onsen UI bug reports, feature requests and questions, please use the Onsen UI GitHub issues page. For help with Monaca, please contact Monaca Support Team.

Thank you to all our community for your contributions to the forum. We look forward to hearing from you in the new communication channels.

After adding <Splitter> menu, Back button is not showing up in next navigated Page



  • Happy New Year to everyone!

    I’m having an unexpected behavior using the <Splitter> menu. I’m using React and intend to setup an HOC that adds the <Splitter> Menu to any page. Here is the HOC (most parts inspired from [great!] documentation):

    import React, { Component } from 'react';
    import {connect} from 'react-redux';
    import {bindActionCreators} from 'redux';
    import * as Actions from '../actions';
    
    import {Page, Splitter, SplitterSide, SplitterContent, List, ListItem} from 'react-onsenui';
    
    import SignIn from '../components/auth/SignIn';
    
    export default function (ComposedComponent) {
    	class AddSplitterContent extends Component {
    		constructor (props) {
    			super(props);
    		}
    		render () {
    			const {splitterOpen, actions, navigator} = this.props;
    			return(
    				<Splitter>
    					<SplitterSide
    						style={{
    								boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)'
    						}}
    						side='left'
    						width={250}
    						collapse={true}
    						isSwipeable={true}
    						isOpen={splitterOpen}
    						onClose={() => actions.splitterSetClose()}
    						onOpen={() => actions.splitterSetOpen()}
    					>
    						<Page>
    							<List
    								dataSource={
    									[{title: 'Sign out', action: () => {
    										actions.signOutUser();
    									}}]
    								}
    								renderRow={(menu) => (
    								<ListItem key={menu.title} onClick={menu.action} tappable>{menu.title}</ListItem>
    								)}
    							/>
    						</Page>
    					</SplitterSide>
    					<SplitterContent>
    						<ComposedComponent {...this.props} />
    					</SplitterContent>
    				</Splitter>
    			);
    		}
    	}
    	const mapStateToProps = (state) => ({
    		splitterOpen: state.ui.splitterOpen
    	});
    	const mapDispatchToProps = (dispatch) => {
    		return {
    			actions: bindActionCreators(Actions, dispatch)
    		};
    	};
    	return connect(
    		mapStateToProps, mapDispatchToProps
    	)(AddSplitterContent);
    }
    

    This HOC works well and I can plug in the <Splitter> wherever I need.

    Having said that, the behavior I’m observing is following.

    • Without HOC or
    export default addSplitterContent(MainPage);
    

    The Navigator’s next page has the “Back” Button on top left of the Page (that is the expected behavior).

    • With HOC or
    export default addSplitterContent(MainPage);
    

    The Navigator’s next page doesn’t have the “Back” Button on top left of the Page (that is the expected behavior).

    What I noticed when inspecting the components within Chrome is that there is a tiny difference between both cases:

    • Without HOC
      <ons-back-button class=“back-button” style=“display: inline-block;”><span class=“back-button__icon”></span><span class=“back-button__label”>Back</span></ons-back-button>
    • With HOC
      <ons-back-button class=“back-button” style=“display: none;”><span class=“back-button__icon”></span><span class=“back-button__label”>Back</span></ons-back-button>

    Does this have something to do with the Navigator stack? I read from the doc that when the stack is empty then the “Back” Button will not show up. I checked that in my code and there are 2 elements in the stack (which is expected!).

    Sorry to be so verbose but the problematic is bit difficult to describe in a shorter way.

    Thanks for any hint/support the community can provide,
    J.



  • Anybody?
    J.



  • @jabidof Sorry, I don’t work with React, so I don’t know how to give you any guidance on this. I know it works, so there is an issue with the navigation stack. Onsen auto adds the back buttons when it sees the navigation stack is greater than 1, if the button is not showing, then I would assume the stack is 0 in size. Have you tried dumping the length to see what it shows?



  • Hi,
    Thanks for your input. Here is the “navigator” console.log dump:
    0_1484506966478_Capture d’écran 2017-01-15 à 20.01.18.png
    I can see a length of 2. Is it what you want me to dump?

    Thanks for your help,
    J.



  • @jabidof Hmm, well definitely shows 2 pages and 2 routes, so, I don’t know. Apologies for not knowing more about react.



  • @munsterlander
    Some news… I added a button in the toolbar whose action is

    onClick={() => navigator.popPage()}
    

    Here is the result in the console:
    0_1484594896522_Capture d’écran 2017-01-16 à 20.28.01.png

    I’m puzzled… This shows that there is a Navigator instance “somewhere” that is not the one I believe i’m using.
    How can I further debug this?

    Thanks for any help.
    J.



  • @munsterlander @Fran-Diox
    I’m able to supply full code that shows the issue. The code is based on @argelius code https://github.com/argelius/react-onsenui-redux-weather
    I made a tiny change by adding the side menu Splitter component and the above described behavior happens.

    It is now clear that there is a BUG in the REACT side menu Splitter component.

    Would this help in the debug process?

    Thanks
    J.



  • @jabidof Yes, if you can post all your code or a github, I will take a look at it. Just understand, I am not a react guy so I can only really look at the Onsen bits.


  • Onsen UI

    @jabidof What’s the order of the routing components? I think the Splitter should be the parent of Navigator for this to work. Splitter > SplitterContent > Navigator. Is that correct?



  • @Fran-Diox @munsterlander

    in main index.js:

    ...
    render(
      <AppContainer>
        <Provider store={store}>
          <App />
        </Provider>
      </AppContainer>,
      rootElement
    ))
    ...
    

    in App.js:

    ...
    const renderPage = (route, navigator) => (
      <route.component key={route.key} navigator={navigator} />
    );
    
    const App = () => (
      <Navigator
    		key='TOTO'
        renderPage={renderPage}
        initialRoute={{component: MainPage, key: 'MAIN_PAGE'}}
      />
    );
    ...
    

    Finally the MainPage.js:

    ...
    const MainPage = ({navigator, splitterOpen, actions}) => (
    	<Splitter>
    		<SplitterSide
    			style={{ boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)' }}
    			side='left'
    			width={250}
    			collapse={true}
    			isSwipeable={true}
    			isOpen={splitterOpen}
    			onClose={() => actions.splitterSetClose()}
    			onOpen={() => actions.splitterSetOpen()}
    		>
    			<Page>
    				<List
    					dataSource={[{title: 'Sign out', action: () => { console.log('sign out...'); }}]
    					}
    					renderRow={(menu) => (
    					<ListItem key={menu.title} onClick={menu.action} tappable>{menu.title}</ListItem>
    					)}
    				/>
    			</Page>
    		</SplitterSide>
    		<SplitterContent>
    			<Page renderToolbar={() => <NavBar title='Onsen Weather' navigator={navigator} />}>
    				<LocationList navigator={navigator} />
    				<AddLocation />
    			</Page>
    		</SplitterContent>
    	</Splitter>
    );
    ...
    

    J.



  • I just tried this in App.js:

    ...
    const App = ({splitterOpen, actions}) => (
    	<Splitter>
    		<SplitterSide
    			style={{ boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)' }}
    			side='left'
    			width={250}
    			collapse={true}
    			isSwipeable={true}
    			isOpen={splitterOpen}
    			onClose={() => actions.splitterSetClose()}
    			onOpen={() => actions.splitterSetOpen()}
    		>
    			<Page>
    				<List
    					dataSource={[{title: 'Sign out', action: () => { console.log('sign out...'); }}]
    					}
    					renderRow={(menu) => (
    					<ListItem key={menu.title} onClick={menu.action} tappable>{menu.title}</ListItem>
    					)}
    				/>
    			</Page>
    		</SplitterSide>
    		<SplitterContent>
    		<Navigator
    			key='TOTO'
    			renderPage={renderPage}
    			initialRoute={{component: MainPage, key: 'MAIN_PAGE'}}
    		/>
    		</SplitterContent>
    	</Splitter>
    );
    ...
    

    And the back button now appears.
    I think this should be added to the doc.
    I’ll update my own code later and let you know the outcome.
    J.



  • @Fran-Diox @Onsen-UI
    That was it! Thanks for the input!

    As I said, I spent few hours digging into this. I’d be happy for the community to find this info in the React DOC (which is already excellent!).

    J.


  • Onsen UI

    @jabidof I supposed that could be the case. I mentioned this when writing the docs but perhaps it should be more extense:

    Notice that loading new content in any of these frames will completely remove the previous loaded content. For more complex navigation consider nesting <ons-navigator> inside <ons-splitter-content>.

    Basically, in your example your Navigator always has 1 child, the Splitter. You are changing the content of the Splitter but that does no affect the Navigator stack.

    Glad it was helpful!



  • @Fran-Diox
    I’m hitting some (maybe basic) issue. You mentioned before that the the Splitter should be the parent of Navigator for this to work. But then, how can I pass the APP Navigator instance to the Page within the SplitterSide component?

    Am I missing something simple?

    J.