Jump to a specific tab from a different page. Binding dynamically <PageControl> and <Each>

My app has a number of pages and every page has two or more tabs. The tabs are dinamically generated by a JSON fetched via a API. Every tab is a <Page>.

Is it possible to jump via JavaScript to a specific tab from a certain page?

PAGE 1 has [tab A], [tab B], [tab C]
PAGE 2 has [tab D], [tab E]

How can I let a user click a button for example in [tab B] and go directly to [tab E]?

I can use router.push() for Page1 and Page2 because these are part of <Navigator>. Can I use the same logic for the tabs as these are <Page>s too but without adding the tabs to the route as I don’t want that pressing the back button the user goes back to the previous tabs, but to the previous page.

Following there’s a full working code that mimics my pages and tabs.

MainView.UX

<App>
    <JavaScript>
        var Observable = require("FuseJS/Observable");

    </JavaScript>

    <Router ux:Name="router" />

    <Navigator DefaultPath="page1">
        <Page1 ux:Template="page1" router="router" />                       
        <Page2 ux:Template="page2" router="router" /> 
    </Navigator>
</App>

Page1.UX

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

        var json = {
            "events": [
                {
                    category: "Music",
                    items: [
                        {"title": "Music. Faucibus dignissim parturient."},
                        {"title": "Music. Taciti ante scelerisque consequat."}
                    ]
                },
                {
                    category: "Theatre",
                    items: [
                        {"title": "Theatre. Condimentum adipiscing leo."}
                    ]
                },
                {
                    category: "Shows",
                    items: [
                        {"title": "Shows. Ut vestibulum tincidunt consectetur."},
                        {"title": "Shows. Parturient mi urna commodo."},
                        {"title": "Shows. Pharetra pretium nisl felis."}
                    ]
                }
            ]
        };

        data.replaceAll(json.events);
   
        
        module.exports = {
            data: data,
            gotoPage1: gotoPage1,
            gotoPage2: gotoPage2
        };

        function gotoPage1(){
            router.push('page1');
        }
        
        function gotoPage2(){
            router.push('page2');
        }

    </JavaScript>
    
    <Router ux:Dependency="router" />

    <ClientPanel>

        <StackPanel Alignment="Center">
            <Button Text="Goto page 2">
                <Clicked>
                    <Callback Handler="{gotoPage2}" />
                </Clicked>
            </Button>
        </StackPanel>

        <Panel Dock="Top">
            <PageIndicator Navigation="mainNav" Orientation="Horizontal" ItemSpacing="10" Alignment="Left" Margin="5">
                <DockPanel ux:Template="Dot" Color="#CCC" Padding="10,5">
                    <Text Color="#000" Value="{Page Title}"/>
                    <Clicked>
                        <NavigateTo Target="{Page Visual}"/>
                    </Clicked>
                </DockPanel>
            </PageIndicator>
        </Panel>
        
        <Page ux:Class="MyPage1">
            <ScrollView Margin="0,0,0,0">
                <StackPanel ItemSpacing="6" >
                    <Each Items="{items}">
                        <Text Value="{title}" />
                    </Each>
                </StackPanel>
            </ScrollView>
        </Page>
        
        <PageControl ux:Name="mainNav">
            <Each Items="{data}">
                <MyPage1 Title="{category}" />    
            </Each>
        </PageControl>

    </ClientPanel>
</Page>

Page2.UX

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

        var json = {
            "events": [
                {
                    category: "Food",
                    items: [
                        {"title": "Food. Pharetra pretium nisl felis."},
                        {"title": "Food. Ut vestibulum tincidunt consectetur."}
                    ]
                },
                {
                    category: "Cinema",
                    items: [
                        {"title": "Cinema. Parturient mi urna commodo."}
                    ]
                },
                {
                    category: "Games",
                    items: [
                        {"title": "Games. Taciti ante scelerisque consequat."},
                        {"title": "Games. Condimentum adipiscing leo."},
                        {"title": "Games. Faucibus dignissim parturient."}
                    ]
                }
            ]
        };

        data.replaceAll(json.events);
   
               
        module.exports = {
            data: data,
            gotoPage1: gotoPage1,
            gotoPage2: gotoPage2
        };

        function gotoPage1(){
            router.push('page1');
        }
        
        function gotoPage2(){
            router.push('page2');
        }

    </JavaScript>
    
    <Router ux:Dependency="router" />

    <ClientPanel>

        <StackPanel Alignment="Center">
            <Button Text="Goto page 1">
                <Clicked>
                    <Callback Handler="{gotoPage1}" />
                </Clicked>
            </Button>
        </StackPanel>

        <Panel Dock="Top">
            <PageIndicator Navigation="mainNav" Orientation="Horizontal" ItemSpacing="10" Alignment="Left" Margin="5">
                <DockPanel ux:Template="Dot" Color="#CCC" Padding="10,5">
                    <Text Color="#000" Value="{Page Title}"/>
                    <Clicked>
                        <NavigateTo Target="{Page Visual}"/>
                    </Clicked>
                </DockPanel>
            </PageIndicator>
        </Panel>
        
        <Page ux:Class="MyPage2">
            <ScrollView Margin="0,0,0,0">
                <StackPanel ItemSpacing="6" >
                    <Each Items="{items}">
                        <Text Value="{title}" />
                    </Each>
                </StackPanel>
            </ScrollView>
        </Page>
        
        <PageControl ux:Name="mainNav">
            <Each Items="{data}">
                <MyPage2 Title="{category}" />    
            </Each>
        </PageControl>

    </ClientPanel>
</Page>

PageControl has a property called Active which takes the Name of the desired Page as an argument. So just give each page a name and dynamically point the Active property of your PageControl in JavaScript and it should work.

Like this (excerpt from https://fuseopen.com/docs/fuse/controls/pagecontrol.html):

<DockPanel>
    <JavaScript>
        var Observable = require("FuseJS/Observable");
        var currentPage = Observable("page1");
        function clickHandler() {
            currentPage.value = "page1";
        }
        module.exports = {
            clickHandler: clickHandler,
            currentPage: currentPage
        };
    </JavaScript>
    <PageControl Active="{currentPage}">
        <Panel Name="page1" Background="Red"/>
        <Panel Name="page2" Background="Green"/>
        <Panel Name="page3" Background="Blue"/>
    </PageControl>
    <Button Text="Home" Clicked="{clickHandler}" Dock="Bottom"/>
</DockPanel>

PageControl also has a javascript method goto to go to the desired page. For more information about Navigation and PageControl take a look at this Fuse Samples: https://github.com/fuse-open/fuse-samples/tree/master/Samples/UIStructure/Navigation I think it has a similar case with yours

Thank you guys for the prompt answers but I didn’t manage to solve my problem as suggested.

I’m trying to access pages directly between different <PageControl> as described in the picture below, not within the same <PageControl>.

Ok, here’s the logic in a nutshell to do that…

  • From the Navigator, you pass in a router to each Page.

  • Then in Page A, when you click a button or whatever your trigger is, you tell the router to go to Page C but you also pass in arguments/parameters.

  • In Page C, you listen for a parameter being changed.

  • When the parameter is changed, you change the Observable that controls the PageControls page.

1 Like

Here’s some sample code…

Navigator:

<Router ux:Name="router" />
<Navigator ux:Name="navigator">
    <PageA ux:Template="pageA" router="router" />
    <PageC ux:Template="pageC" router="router" />
...

JS for routing between pages:

router.push('pageC', {
    subPage: 'page2'
});

Page A:

<Page ux:Class="PageA">
    <Router ux:Dependency="router" />
    <JavaScript>
        function gotoPageC() {
            router.push('pageC', {
                subPage: 'page2'
            });
        }
        function clickedButton() {
            //do some stuff
            gotoPageC();
        }

Page C:

<Page ux:Class="PageC">
    <Router ux:Dependency="router" />
    <JavaScript>
        var Observable = require('FuseJS/Observable');
        var subPage = Observable();
        this.Parameter.onValueChanged(module, function(x) {
            subPage.value = x.subPage;
        });
        module.exports = {
            subPage
        };
    </JavaScript>
    <PageControl Active="{subPage}">
        <Panel ux:Name="page1" />
        <Panel ux:Name="page2" />
...
1 Like

Ok got it! Thank you very much!

I tried to replicate Andrew’s suggestion using dinamically generated content (JSON) but I don’t understand why it does not work.

It seems that when pages are dynamically added, binding to ux:Name is not possible.

Infact, if in PageC.ux you remove the <Each> and you uncomment the commented block underneath the <Each> , the code will work.

Expected result: click Goto page C, tab Cinema and should see ‘Tab CINEMA’ of Page A

Following the full code:

MainView.ux

<App>
    <JavaScript>
        var Observable = require("FuseJS/Observable");
    </JavaScript>

    <Router ux:Name="router" />

    <Navigator DefaultPath="pageA">
        <PageA ux:Template="pageA" router="router" />                       
        <PageC ux:Template="pageC" router="router" /> 
    </Navigator>
</App>

PageA.ux

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

        var json = {
            "events": [
                {
                    category: "Music",
                    items: [
                        {"title": "Tab MUSIC."},
                    ]
                },
                {
                    category: "Theatre",
                    items: [
                        {"title": "Tab THEATRE."}
                    ]
                },
                {
                    category: "Shows",
                    items: [
                        {"title": "Tab SHOWS."},
                    ]
                }
            ]
        };

        data.replaceAll(json.events);

        module.exports = {
            data: data,
            gotoPageC: gotoPageC,
            clickedButton: clickedButton
        };

   
        function gotoPageC() {
            router.push('pageC', {
                subPage: 'Cinema'
            });
        }
        function clickedButton() {
            //do some stuff
            gotoPageC();
        }

    </JavaScript>
    
    <Router ux:Dependency="router" />

    <ClientPanel>

        <StackPanel Alignment="Center">
            <Text TextAlignment="Center" Value="PAGE A" Margin="0,0,0,20" />
            <Button Text="Goto page C, tab 'Cinema'">
                <Clicked>
                    <Callback Handler="{clickedButton}" />
                </Clicked>
            </Button>
        </StackPanel>
        
        <Panel Dock="Top">
            <PageIndicator Navigation="mainNav" Orientation="Horizontal" ItemSpacing="10" Alignment="Left" Margin="5">
                <DockPanel ux:Template="Dot" Color="#CCC" Padding="10,5">
                    <Text Color="#000" Value="{Page Title}"/>
                    <Clicked>
                        <NavigateTo Target="{Page Visual}"/>
                    </Clicked>
                </DockPanel>
            </PageIndicator>
        </Panel>
        
        <PageControl ux:Name="mainNav">
            <Each Items="{data}">
                <MyPage1 Title="{category}" Margin="0,20,0,0" />    
            </Each>
        </PageControl>

    </ClientPanel>

            <Page ux:Class="MyPage1">
            <ScrollView Margin="0,0,0,0">
                <StackPanel ItemSpacing="6" >
                    <Each Items="{items}">
                        <Text Value="{title}" />
                    </Each>
                </StackPanel>
            </ScrollView>
        </Page>
</Page>

PageC.ux

<Page ux:Class="PageC">
    <JavaScript>
        var Observable      = require("FuseJS/Observable");
        var data            = Observable();
        
        var subPage = Observable();
        
        this.Parameter.onValueChanged(module, function(x) {
            subPage.value = x.subPage;
            console.log("subPage = " + subPage.value);
        });

        
        var json = {
            "events": [
                {
                    category: "Food",
                    items: [
                        {"title": "Tab FOOD. Pharetra pretium nisl felis."},
                    ]
                },
                {
                    category: "Cinema",
                    items: [
                        {"title": "Tab CINEMA. Parturient mi urna commodo."}
                    ]
                },
                {
                    category: "Games",
                    items: [
                        {"title": "Tab GAMES. Taciti ante scelerisque consequat."},
                    ]
                }
            ]
        };

        data.replaceAll(json.events);
   
        

        module.exports = {
            data: data,
            gotoPageA: gotoPageA,
            subPage
        };

        function gotoPageA(){
            router.push('pageA');
        }
        
    </JavaScript>
    
    <Router ux:Dependency="router" />

    <ClientPanel>

        <StackPanel Alignment="Center">
            <Text TextAlignment="Center" Value="PAGE C" Margin="0,0,0,20" />
            <Button Text="Goto page A">
                <Clicked>
                    <Callback Handler="{gotoPageA}" />
                </Clicked>
            </Button>
        </StackPanel>

        <Panel Dock="Top">
            <PageIndicator Navigation="mainNav" Orientation="Horizontal" ItemSpacing="10" Alignment="Left" Margin="5">
                <DockPanel ux:Template="Dot" Color="#CCC" Padding="10,5">
                    <Text Color="#000" Value="{Page Title}"/>
                    <Clicked>
                        <NavigateTo Target="{Page Visual}"/>
                    </Clicked>
                </DockPanel>
            </PageIndicator>
        </Panel>
        
        <PageControl ux:Name="mainNav" Active="{subPage}">

            <Each Items="{data}">
                <MyPage ux:Name="{category}" Title="{category}" Margin="0,20,0,0" />
            </Each>
            <!-- The following code represents what does the above <Each> --> 
            <!--
            <Page ux:Name="Food" Title="Food" Margin="0,20,0,0">
                <Text Value="Tab FOOD" />
            </Page>
            <Page ux:Name="Cinema" Title="Cinema" Margin="0,20,0,0">
                <Text Value="Tab CINEMA" />
            </Page>
            <Page ux:Name="Games" Title="Games" Margin="0,20,0,0">
                <Text Value="Tab GAMES" />
            </Page>
            -->
        </PageControl>

    </ClientPanel>
        
    <Page ux:Class="MyPage">
        <ScrollView Margin="0,0,0,0">
            <StackPanel ItemSpacing="6" >
                <Each Items="{items}">
                    <Text Value="{title}" />
                </Each>
            </StackPanel>
        </ScrollView>
    </Page>

</Page>

[SOLVED]
As I suspected, when pages are dynamically added, binding to ux:Name is not possible. You need to use ActiveIndex.

Below the new PageC.ux: I create an array with the categories names so I can get their index, then having a subPage.value sent from PageA.ux I look for the category with the same index which I then pass to the Observable {activeIndex} to jump the relative tab.

PageC.ux

<Page ux:Class="PageC" Reuse="None">
    <JavaScript>
        var Observable      = require("FuseJS/Observable");
        var data            = Observable();
                    
        var subPage         = Observable();
        var activeIndex     = Observable(0);

        var json = {
            "events": [
                {
                    category: "Food",
                    items: [
                        {"title": "Tab FOOD."},
                    ]
                },
                {
                    category: "Cinema",
                    items: [
                        {"title": "Tab CINEMA."}
                    ]
                },
                {
                    category: "Games",
                    items: [
                        {"title": "Tab GAMES."},
                    ]
                }
            ]
        };
        
        
        data.replaceAll(json.events);
 
 
        categories = [];

 
        data.forEach(function(items){
            categories.push(items.category);
        });


        this.Parameter.onValueChanged(module, function(x) {
            subPage.value = x.subPage;
            activeIndex.value = categories.indexOf(subPage.value);
        });
   
        

        module.exports = {
            data: data,
            gotoPageA: gotoPageA,
            subPage: subPage,
            activeIndex: activeIndex
        };


        function gotoPageA(){
            router.push('pageA');
        }


        
    </JavaScript>
    
    <Router ux:Dependency="router" />

    <ClientPanel>

        <StackPanel Alignment="Center">
            <Text TextAlignment="Center" Value="PAGE C" Margin="0,0,0,20" />
            <Button Text="Goto page A">
                <Clicked>
                    <Callback Handler="{gotoPageA}" />
                </Clicked>
            </Button>
        </StackPanel>

        <Panel Dock="Top">
            <PageIndicator Navigation="mainNav" Orientation="Horizontal" ItemSpacing="10" Alignment="Left" Margin="5">
                <DockPanel ux:Template="Dot" Color="#CCC" Padding="10,5">
                    <Text Color="#000" Value="{Page Title}"/>
                    <Clicked>
                        <NavigateTo Target="{Page Visual}"/>
                    </Clicked>
                </DockPanel>
            </PageIndicator>
        </Panel>
        
        <PageControl ux:Name="mainNav" Active="{subPage}" ActiveIndex="{activeIndex}">
            <Each Items="{data}">
                <MyPage Title="{category}" Margin="0,20,0,0" />
            </Each>
        </PageControl>

    </ClientPanel>
        
    <Page ux:Class="MyPage">
        <ScrollView Margin="0,0,0,0">
            <StackPanel ItemSpacing="6" >
                <Each Items="{items}">
                    <Text Value="{title}" />
                </Each>
            </StackPanel>
        </ScrollView>
    </Page>

</Page>
1 Like