Navigator. Back button won't go back on multipage app

I’m building a multipage app. Some pages have tabs that display different content. The problem is that I’m not able to make the back button (Android) work. I did look carefully at the Cattr app and at the Hikr app but I’m missing something or I did not understand the logic behind Navigator.

I made a stripped version of the app that can be downloaded as it is not practical to report the complete code inside a post or to copy/paste it for test purposes.

The APP has a Homepage, a Music and a Show page and a Detail page. The content of the Music and Shows pages is divided in tabs. The tabs and the content is fetch from a API (but in the downloadable version above it is included inside the files as json).

The problem is that despite Router I can’t make the back button (Android) work. I keep getting the error Cannot navigate to "", not found! and Unable to navigate to route: music/.

Every page or class has <Router ux:Dependency="router" /> and Mainview.ux has <Router ux:Name="router" />

The back button works only for the ‘first’ level when I jump from Homepage to a subpage and I press the back button. If, from this subpage I click a second subpage and then I press the back button, it does not work:

HomePage -> Music WORKS

HomePage -> Shows WORKS

HomePage -> Music -> Shows NOT WORKS

HomePage -> Shows -> Detail NOT WORKS

HomePage -> Music -> Shows -> Detail NOT WORKS

The back button should send the user to the previous page even if a tab has been clicked. Anyway here is part of the stripped version of pages I’m working on (but please try the downloadable version):

MAINVIEW.UX

<App>
    <JavaScript>
    
    function gotoShows() {
        router.push("shows");
    };

    function gotoMusic() {
        router.push("music");
    };

    module.exports = {
        clickedShows: gotoShows,
        clickedMusic: gotoMusic
    };

</JavaScript>


<Router ux:Name="router" />

<ClientPanel>

    <DockPanel Dock="Top" Height="56">
        <Text ux:Name="pageName" Value="" FontSize="20" Alignment="Center" />
    </DockPanel>

    <DockPanel>
        <Navigator DefaultPath="home">
            <HomePage ux:Template="home" router="router"> 
                <Activated>
                    <Set Target="pageName.Value" Value="HOME"/>
                </Activated>
            </HomePage>
            <MusicPage ux:Template="music" router="router"> 
                <Activated>
                    <Set Target="pageName.Value" Value="MUSIC"/>
                </Activated>
            </MusicPage>
            <ShowsPage ux:Template="shows" router="router">
                <Activated>
                    <Set Target="pageName.Value" Value="SHOWS"/>
                </Activated>
            </ShowsPage>
            <DetailPage ux:Template="detail" router="router" />
        </Navigator>
    </DockPanel>

</ClientPanel>

<Page ux:Class="MyPage">

    <Router ux:Dependency="router" />

    <ScrollView Margin="0,0,0,0">
        <StackPanel ItemSpacing="6" >
            <Each Items="{items}">
                <StackPanel>
                        <Clicked>
                            <Callback Handler="{gotoDetail}" />
                        </Clicked>
                    <Text Value="{title}" />
                </StackPanel>
            </Each>
        </StackPanel>
    </ScrollView>
</Page>

<Rectangle ux:Class="Indicator" Alignment="Bottom" Height="6" Color="#950017" Margin="0,0,0,-8">
    <LayoutAnimation>
        <Move RelativeTo="WorldPositionChange" X="1" Duration="0.4" Easing="BackIn"/>
    </LayoutAnimation>
</Rectangle>  

</App>

HOMEPAGE.UX

<Page ux:Class="HomePage">
<JavaScript>
    var Observable      = require("FuseJS/Observable");
    var data            = Observable();

    module.exports = {
        gotoMusic:  gotoMusic,
        gotoShows:  gotoShows,
    };
    
    function gotoShows() {
        router.push("shows");
    };

    function gotoMusic() {
        router.push("music");
    };
    
</JavaScript>

<Router ux:Dependency="router" />

<StackPanel Alignment="Center" ItemSpacing="20" >
    <Text Value="Goto Music">
        <Clicked Handler="{gotoMusic}" />
    </Text> 
    <Text Value="Goto Shows">
        <Clicked Handler="{gotoShows}" />
    </Text>
</StackPanel>

</Page>

MUSIC.UX

<Page ux:Class="MusicPage">
<JavaScript>
    var Observable      = require("FuseJS/Observable");
    var data            = Observable();


    var json = {
        "events": [
            {
                category: "Live",
                items: [
                    {
                        "title": "Live. Faucibus dignissim parturient.",
                        "description": "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium."    
                    },
                    {
                        "title": "Live. Taciti ante scelerisque consequat.",
                        "description": "Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit."   
                    }
                ]
            },
            {
                category: "Dance",
                items: [
                    {
                        "title": "Dance. Condimentum adipiscing leo.",
                        "description": "At vero eos et accusamus et iusto odio dignissimos ducimus."       
                    }
                ]
            },
            {
                category: "Party",
                items: [
                    {
                        "title": "Party. Ut vestibulum tincidunt consectetur.",
                        "description": "Ut enim ad minima veniam, quis nostrum exercitationem."       
                    },
                    {
                        "title": "Party. Parturient mi urna commodo.",
                        "description": "Quis autem vel eum iure reprehenderit qui in ea."   
                    },
                    {
                        "title": "Party. Pharetra pretium nisl felis.",
                        "description": "Et harum quidem rerum facilis est et expedita distinctio."   
                    }
                ]
            }
        ]
    };

    data.replaceAll(json.events);

    module.exports = {
        data:           data,
        gotoHome:       gotoHome,
        gotoShows:      gotoShows,
        gotoDetail:     gotoDetail,
    };
    
    function gotoShows() {
        router.push("shows");
    };

    function gotoHome() {
        router.push("home");
    };

    function gotoDetail(sender) {
        router.push("detail", { details: sender });
    };
</JavaScript>


    <Router ux:Dependency="router" />

    <StackPanel Alignment="Center" ItemSpacing="20" >
        <Text Value="Goto Home">
            <Clicked Handler="{gotoHome}" />
        </Text> 
        <Text Value="Goto Shows">
            <Clicked Handler="{gotoShows}" />
        </Text>
    </StackPanel>

    <DockPanel>
        <Panel Dock="Top">
            <ScrollView AllowedScrollDirections="Horizontal">
                <PageIndicator Navigation="mainNav" Orientation="Horizontal" Alignment="Left" Margin="6,6,6,6">
                    <DockPanel ux:Template="Dot" Width="100" Height="40">
                        <Rectangle Height="40">
                            <SolidColor Color="#FFFFFF" />
                            <Text TextAlignment="Center" Alignment="Center" Value="{Page Title}" />
                            <WhileActive Threshold="0.4">
                                <Indicator />
                            </WhileActive>
                            <Clicked>
                                <NavigateTo Target="{Page Visual}"/>
                            </Clicked>
                        </Rectangle>
                    </DockPanel>
                </PageIndicator>
            </ScrollView>
        </Panel>
        
        <PageControl ux:Name="mainNav">
            <Each Items="{data}">
                <MyPage Title="{category}" router="router"/>    
            </Each>
        </PageControl>
    </DockPanel>

Thank you.

This happens because a nested navigation interferes with the state of the router. In your case, the PageControls.

If you don’t need to control the PageControl instances using Router, you can add IsRouterOutlet="false" property on them, like so:

<PageControl ux:Name="mainNav" IsRouterOutlet="false">

Alternatively, you could hack around this on the child pages using OnBackButton and GoBack/GoForward targeting the needed router outlet with explicit NavigationContext set:

<OnBackButton>
    <GoBack NavigationContext="uxNameOfParentLevelNavigator" />
</OnBackButton>

Hope this helps!

Thank you!

 <PageControl ux:Name="mainNav" IsRouterOutlet="false">

Worked perfectly!