Implement AlternateRoot

I want to inject difference function inside alternateRoot . I totally have 6 files and they serves the following purpose.

MainView.ux - App contains All Subpage

<App>
	<Router ux:Name="router" />

	<DockPanel>
		
		<StackPanel Dock="Top" Background="#3CB5D0">
	
			<Panel ux:Name="navBar" Dock="Top" Height="50">
				<WhileCanGoBack>
					<Panel ux:Name="backButton" Width="90" Height="50" Alignment="Left" 
					       Padding="20,0,0,0" HitTestMode="LocalBounds">
							<Text Alignment="Center" Margin="5,0,0,0" FontSize="18" Color="#fff" Dock="Right">
								BACK
							</Text>
				
						<Clicked>
							<GoBack />
						</Clicked>
					</Panel>
				</WhileCanGoBack>
				
			</Panel>
		</StackPanel>
		

		<Navigator DefaultPath="subPage1">
			<SubPage1 ux:Template="subPage1" navBar="navBar" router="router"/>
			<SubPage2 ux:Template="subPage2" navBar="navBar" router="router"/>
		</Navigator>
	</DockPanel>
</App>

Subpage1.ux

<Page ux:Class="SubPage1">

	<Visual ux:Dependency="navBar" />
	<Panel>
		<AlternateRoot ParentNode="navBar">
                        <Text>PAGE2</Text>
		</AlternateRoot>
	</Panel>
</Page>

Subpage2.ux

<Page ux:Class="SubPage2">

	<Visual ux:Dependency="navBar" />
	<Panel>
		<AlternateRoot ParentNode="navBar">
                        <Text>PAGE1</Text>
		</AlternateRoot>
	</Panel>
</Page>

What I want to achieve is to implement two difference actions in each page ,
Those actions can disable/enable the element ux:Name=“backbuttom”,
and those two actions also visually display a relative Panel to cover the whole navBar,

Example like Subpage1 has an extra search icon at the right corner and click that icon will disable the action the ux:Name=“backbuttom” elements,
Then, it will show a search input field that cover the textfield “PAGE1” or “PAGE2”

Hi Sky,

you should use AlternateRoot to only inject visuals in necessary places. What you have described as your target goal requires the use of UX properties, WhileActive, WhileTrue and Change triggers and maybe even something else.

Using your snippets, I have put together a little example that shows what you can and what you should do. Hope this helps!

<App>
    <Router ux:Name="router" />
    <DockPanel>
        <NavBar ux:Name="navBar" Dock="Top" Height="50" Background="#3CB5D0" />
        <Navigator DefaultPath="subPage1">
            <SubPage1 ux:Template="subPage1" navBar="navBar" router="router">
                <WhileActive>
                    <Change navBar.backBtnEnabled="false" />
                </WhileActive>
            </SubPage1>
            <SubPage2 ux:Template="subPage2" navBar="navBar" router="router">
                <WhileActive>
                    <Change navBar.backBtnEnabled="true" />
                </WhileActive>
            </SubPage2>
        </Navigator>
    </DockPanel>

    <Panel ux:Class="NavBar">
        <bool ux:Property="backBtnEnabled" />
        <WhileTrue Value="{ReadProperty backBtnEnabled}">
            <Panel ux:Name="backButton" Width="90" Height="50" Alignment="Left" Padding="20,0,0,0" HitTestMode="LocalBounds">
                <Text Value="BACK" Alignment="Center" Margin="5,0,0,0" FontSize="18" Color="#fff" Dock="Right" />
                <Clicked>
                    <GoBack />
                </Clicked>
            </Panel>
        </WhileTrue>
    </Panel>

    <Page ux:Class="SubPage1">
        <Router ux:Dependency="router" />
        <Visual ux:Dependency="navBar" />
        <JavaScript>
            module.exports.navigate = function() {
                router.push("subPage2");
            };
        </JavaScript>
        <Text Value="page 1" Alignment="Center" />
        <Clicked>
            <Callback Handler="{navigate}" />
        </Clicked>
        <WhileActive>
            <AlternateRoot ParentNode="navBar">
                <Text Alignment="Center">PAGE1</Text>
            </AlternateRoot>
        </WhileActive>
    </Page>

    <Page ux:Class="SubPage2">
        <Router ux:Dependency="router" />
        <Visual ux:Dependency="navBar" />
        <Text Value="page 2" Alignment="Center" />
        <WhileActive>
            <AlternateRoot ParentNode="navBar">
                <Text Alignment="Center">PAGE2</Text>
            </AlternateRoot>
        </WhileActive>
    </Page>

</App>

Is that wrong if I do the following. I replace <Visual ux:Dependency="navBar" /> to <Navbar ux:Dependency="navBar" /> in Subpage2 , and add <Change navBar.backBtnEnabled="true" /> inside<WhileActive>Tab?

Just like the following. It was because I found it work but I dont know why.

 <Page ux:Class="SubPage2">
        <Router ux:Dependency="router" />
        <Navbar ux:Dependency="navBar" />
        <Text Value="page 2" Alignment="Center" />
        <WhileActive>
            <Change navBar.backBtnEnabled="true" />
            <AlternateRoot ParentNode="navBar">
                <Text Alignment="Center">PAGE2</Text>
            </AlternateRoot>
        </WhileActive>
    </Page>

No, that is perfectly fine. I just wanted to show you that you can have multiple WhileActive triggers and that they all get executed. You can, of course, do it with the dependency and just one, like this:

<App>
    <Router ux:Name="router" />
    <DockPanel>
        <NavBar ux:Name="navBar" Dock="Top" Height="50" Background="#3CB5D0" />
        <Navigator DefaultPath="subPage1">
            <SubPage1 ux:Template="subPage1" navBar="navBar" router="router" />
            <SubPage2 ux:Template="subPage2" navBar="navBar" router="router" />
        </Navigator>
    </DockPanel>

    <Panel ux:Class="NavBar">
        <bool ux:Property="backBtnEnabled" />
        <WhileTrue Value="{ReadProperty backBtnEnabled}">
            <Panel ux:Name="backButton" Width="90" Height="50" Alignment="Left" Padding="20,0,0,0" HitTestMode="LocalBounds">
                <Text Value="BACK" Alignment="Center" Margin="5,0,0,0" FontSize="18" Color="#fff" Dock="Right" />
                <Clicked>
                    <GoBack />
                </Clicked>
            </Panel>
        </WhileTrue>
    </Panel>

    <Page ux:Class="SubPage1">
        <Router ux:Dependency="router" />
        <NavBar ux:Dependency="navBar" />
        <JavaScript>
            module.exports.navigate = function() {
                router.push("subPage2");
            };
        </JavaScript>
        <Text Value="page 1" Alignment="Center" />
        <Clicked>
            <Callback Handler="{navigate}" />
        </Clicked>
        <WhileActive>
            <Change navBar.backBtnEnabled="false" />
            <AlternateRoot ParentNode="navBar">
                <Text Alignment="Center">PAGE1</Text>
            </AlternateRoot>
        </WhileActive>
    </Page>

    <Page ux:Class="SubPage2">
        <Router ux:Dependency="router" />
        <NavBar ux:Dependency="navBar" />
        <Text Value="page 2" Alignment="Center" />
        <WhileActive>
            <Change navBar.backBtnEnabled="true" />
            <AlternateRoot ParentNode="navBar">
                <Text Alignment="Center">PAGE2</Text>
            </AlternateRoot>
        </WhileActive>
    </Page>

</App>

What if I extend the structure like the following.

The Page 1 has two level and Page 2 has one level.

I used the “Home Page” to negative between Page 1 and Page 2, it works fine.
However, I can not further negative form “Page 1 level 1” to “Page 1 level 2” by using router push.

Also, when I clicked the back button from “Page 1 level 1” and goback to ‘Home page’ , the visual in alternative root is remain there.


<App>
    <Router ux:Name="router" />
    <DockPanel>
        <NavBar ux:Name="navBar" Dock="Top" Height="50" Background="#3CB5D0" />
        <Navigator DefaultPath="home">
        	<Home ux:Template="home" navBar="navBar" router="router" />
            <SubPage1 ux:Template="subPage1" navBar="navBar" router="router" />
            <SubPage2 ux:Template="subPage2" navBar="navBar" router="router" />
        </Navigator>
    </DockPanel>

    <Panel ux:Class="NavBar">
        <bool ux:Property="backBtnEnabled" />
        <WhileTrue Value="{ReadProperty backBtnEnabled}">
            <Panel ux:Name="backButton" Width="90" Height="50" Alignment="Left" Padding="20,0,0,0" HitTestMode="LocalBounds">
                <Text Value="BACK" Alignment="Center" Margin="5,0,0,0" FontSize="18" Color="#fff" Dock="Right" />
                <Clicked>
                    <GoBack />
                </Clicked>
            </Panel>
        </WhileTrue>
    </Panel>
      
     <Page ux:Class="Home">
        <Router ux:Dependency="router" />
        <NavBar ux:Dependency="navBar" />
         <JavaScript>
            module.exports.navigate_to_page1 = function() {
                router.push("subPage1");
            };
             module.exports.navigate_to_page2 = function() {
                router.push("subPage2");
            };
        </JavaScript>
         <WhileActive>
            <Change navBar.backBtnEnabled="false" />
            <AlternateRoot ParentNode="navBar">
                <Text Alignment="Center">Home</Text>
            </AlternateRoot>
        </WhileActive>

        <Text Value="go page 1" Alignment="Top" >
         	<Clicked>
            	<Callback Handler="{navigate_to_page1}" />
        	</Clicked>
    	</Text>

         <Text Value="go page 2" Alignment="Bottom" >
         <Clicked>
            <Callback Handler="{navigate_to_page2}" />
        </Clicked>
    </Text>
    </Page>


    <!--IT HAS 2 level -->
    <Page ux:Class="SubPage1">
        <Router ux:Dependency="router" />
        <NavBar ux:Dependency="navBar" />

          <WhileActive>
            <AlternateRoot ParentNode="navBar">
              
            </AlternateRoot>
        </WhileActive>

         <Navigator DefaultPath="subPage3">
            <SubPage3 ux:Template="subPage3" navBar="navBar" router="router" />
            <SubPage4 ux:Template="subPage4" navBar="navBar" router="router" />
        </Navigator>
    </Page>

    <Page ux:Class="SubPage2">
        <Router ux:Dependency="router" />
        <NavBar ux:Dependency="navBar" />
        <Text Value="page 2" Alignment="Center" />
        <WhileActive>
            <Change navBar.backBtnEnabled="true" />
            <AlternateRoot ParentNode="navBar">
                <Text Alignment="Center">PAGE2 Level 1</Text>
            </AlternateRoot>
        </WhileActive>
    </Page>



    <Page ux:Class="SubPage3">
        <Router ux:Dependency="router" />
        <NavBar ux:Dependency="navBar" />
          <JavaScript>
            module.exports.navigate_to_page1_level2 = function() {
                router.push("subPage4");
            };
 
        </JavaScript>
       
        <WhileActive>
            <Change navBar.backBtnEnabled="true" />
            <AlternateRoot ParentNode="navBar">
                <Text Alignment="Center">PAGE 1 Level 1</Text>
            </AlternateRoot>
        </WhileActive>
         <Text Value="go page 1 Level 2" Alignment="Center" >
         <Clicked>
            <Callback Handler="{navigate_to_page1_level2}" />
        </Clicked>
    </Text>
    </Page>


    <Page ux:Class="SubPage4">
        <Router ux:Dependency="router" />
        <NavBar ux:Dependency="navBar" />
        <Text Value="page 4" Alignment="Center" />
        <WhileActive>
            <Change navBar.backBtnEnabled="true" />
            <AlternateRoot ParentNode="navBar">
                <Text Alignment="Center">PAGE 1 Level 2</Text>
            </AlternateRoot>
        </WhileActive>
    </Page>



</App>

Yes, you can navigate on many levels. To do that, you have two options:

  1. Pass the full path to where you want to go, like so: router.push("subPage1", {}, "subPage4", {}); (note each page accepts params, so it’s “template name, params, template name, params”).
  2. Use relative router functions, see docs: Router interface

That ^^^ might solve the AlternateRoot issue you mentioned, too.

I changed

router.push("subPage1", {}, "subPage4", {});
``` . it works what i want.

But the visual still have some problem when I click goto page 1 then click back to home.

The ``` <Text Alignment="Center">PAGE 1 Level 1</Text> ```  and back button still exist.

![file](https://s3.us-east-2.amazonaws.com/fuse-legacy-forum-assets/PCrHOUJZBNOF-image-1493100372882.59.29 PM.png)

Well, it does make sense when you think about it.

Router and Navigator take care about recycling and reusing page instances, as well as activating and deactivating them. When you go to subPage1/subPage3 path, both the first and second level Navigators get pages activated (you can use <DebugAction Message="Page X activated" /> inside WhileActive/WhileInactive triggers to see this).

Now, when you click Back, only the first level Navigator receives that it needs to switch page back to “home”. The second level Navigator stays intact, and so the “Page 1 Level 1” thing still shows, because that page is still active (even if not in foreground).

To solve this, you again have several ways to go:

  • You could have multiple navigation bars, one for each level and switch those according to which navigation level you are on.
  • If you need a single and properly global navigation bar, use a JavaScript module for it instead.

Since this already covers far more than the initial question and deviates from the topic, I suggest to end this thread here. If you run into further issues, please post very specific, short questions in a new thread.