Accessing component's child node from parents

Hey there,

I created a component called MenuTab, and it’s being used in a page (i.e. HomePage).
In the home page I have a PageControl and I have added a couple of trigger animation on the one of the Page element, like the following. I am having problem in assigning the Move target, as the target is actually in the TabMenu component. Any idea on how to achieve this?
Am i structuring the component in the wrong way? I am just trying to component-ised the TabMenu, so I can re-use it.

<WhileActive Threshold="0.5">
	<Set tabMenu.LayoutMaster="helpSelectedIndicator" />
        <Set tabMenu.StudentButtonSelected="false" />
        <Set tabMenu.HelpButtonSelected="true" />
</WhileActive>
<ActivatingAnimation Scale="0.333">
         <Move Target="indicator" X="1" RelativeTo="PositionOffset" RelativeNode="p2"/>
</ActivatingAnimation>

Hi Kesuma,

it’s impossible to help you with seeing just the snippet you have posted. You need to share a minimal, self-contained, and complete reproduction of the UX you’ve tried to build.

Aside from that, looking at Fuse examples and finding some that deal with tab bar navigation should be a good starting point.

Hello,
Sorry about that

Here are the snippets.

MenuBar Component

<Grid
    ux:Class="nls.MenuBar"
    Dock="Top"
    Padding="10,0,10,0"
    Color="DarkGray"
    Rows="40"
    LayoutMaster="page1SelectedIndicator">

    <JavaScript>
        var goToPage1 = function() {
            router.goto("home", null, "page1");
        };

        var goToPage2 = function() {
            router.goto("home", null, "page2");
        };

        module.exports = {
            goToPage1: goToPage1,
            goToPage2: goToPage2
        };
    </JavaScript>

    <string ux:Property="LayoutMaster" />
    <bool ux:Property="Page1ButtonSelected" />
    <bool ux:Property="Page2ButtonSelected" />

    <Router ux:Dependency="router" />

    <Panel>
        <Grid ColumnCount="2">
            <Panel ux:Name="p1" Column="0" />
            <Panel ux:Name="p2" Column="1" />
        </Grid>
        <Rectangle
            ux:Name="indicator"
            Color="Yellow"
            Height="2"
            Alignment="Bottom"
            ZOffset="0.1"
            LayoutMaster="{ReadProperty LayoutMaster}">
			<LayoutAnimation>
				<Move X="1" Duration="0.3" RelativeTo="PositionChange" Easing="CubicIn" />
			</LayoutAnimation>
		</Rectangle>
        <Grid ColumnCount="2">		
            <nls.TabButton
                Width="100%"
                Column="0"
                ux:Name="page1Button"
                Text="Page 1"
                IsSelected="{ReadProperty Page1ButtonSelected}"
                Tapped="{goToPage1}">
                <Clicked>
                    <Set indicator.LayoutMaster="page1SelectedIndicator" />
                    <Set page1Button.IsSelected="true" />
                    <Set page2Button.IsSelected="false" />
                </Clicked>
                <Panel ux:Name="page1SelectedIndicator" Height="2" Alignment="Bottom"/>
            </nls.TabButton>
            <nls.TabButton
                Width="100%"
                Column="1"
                ux:Name="page2Button"
                Text="Page 2"
                IsSelected="{ReadProperty Page2ButtonSelected}"
                Tapped="{goToPage2}">
                <Clicked>
                    <Set indicator.LayoutMaster="page2SelectedIndicator" />
                    <Set page1Button.IsSelected="false" />
                    <Set page2Button.IsSelected="true" />
                </Clicked>
                <Panel ux:Name="page2SelectedIndicator" Height="2" Alignment="Bottom"/>
            </nls.TabButton>
        </Grid>
    </Panel>
</Grid>

this is how the MenuBar is being used

<Page ux:Class="HomePage">
    <Router ux:Dependency="router" />
    <DockPanel>
        <nls.MenuBar ux:Name="tabMenu" router="router" Page1ButtonSelected="true" />

        <PageControl>
            <NavigationMotion GotoEasing="BackOut" />
            <Page ux:Name="page1" Background="#eee">
				<WhileActive Threshold="0.5">
					<Set tabMenu.LayoutMaster="page1SelectedIndicator" />
                    <Set tabMenu.Page1ButtonSelected="true" />
                    <Set tabMenu.Page2ButtonSelected="false" />
				</WhileActive>
				<PageOne router="router" />
			</Page>
            <Page ux:Name="page2" Background="#eee">
				<WhileActive Threshold="0.5">
					<Set tabMenu.LayoutMaster="page2SelectedIndicator" />
                    <Set tabMenu.Page1ButtonSelected="false" />
                    <Set tabMenu.Page2ButtonSelected="true" />
				</WhileActive>
				<PageTwo />
			</Page>
        </PageControl>
    </DockPanel>
</Page>

What I am trying to achieve is to make the indicator move along as I navigating the sub pages by sliding the page

just like this example https://www.fusetools.com/examples/dynamic-tab-bar, except I break it into components

This is not a minimal, self-contained, and complete reproduction. It’s impossible to copy-paste and run it to see what’s going on because of missing component definitions.

Can you create a single UX file that holds everything (but is still minimal) starting with <App> tag and ending with </App>?

Before that, there’s very little to be said. Data contexts are limited to components and there’s ux:Dependency to work around the limitations.

With a lot of guessing, I came up with something that probably does what you intended to make. Also, this is what we generally mean by “a minimal, self-contained and complete reproduction” - something that you can copy-paste and run.

The main takeaway is that you refer to things in their data contexts. If you need to set a LayoutMaster on something, make sure it’s accessible. If that is not possible, use a ux:Dependency to inject the needed UX node.

Hope this helps!

<App>

    <Panel ux:Class="MenuBar" Color="#333" Height="40" indicatorTarget="page1indicator">

        <Router ux:Dependency="router" />
        <string ux:Property="indicatorTarget" />

        <JavaScript>
        function navigate(args) {
            switch (args.sender) {
                case "page1":
                    router.goto("page1");
                break;
                case "page2":
                    router.goto("page2");
                break;
                default:
                    console.log("MenuBar::navigate() - unknown sender: " + args.sender);
                break;
            }
        }

        module.exports = {
            navigate: navigate
        };
        </JavaScript>

        <Rectangle ux:Name="indicator" Color="#ff0" LayoutMaster="{ReadProperty indicatorTarget}">
            <LayoutAnimation>
                <Move X="1" Duration="0.3" RelativeTo="PositionChange" Easing="CubicIn" />
            </LayoutAnimation>
        </Rectangle>

        <Grid ColumnCount="2">      
            <Panel ux:Name="page1" HitTestMode="LocalBounds">
                <WhileString Value="{ReadProperty indicatorTarget}" Equals="page1indicator">
                    <Change mbOne.IsSelected="true" />
                </WhileString>
                <MenuButton ux:Name="mbOne" Label="Page 1" />
                <Clicked>
                    <Callback Handler="{navigate}" />
                </Clicked>
                <Panel ux:Name="page1indicator" Height="2" Alignment="Bottom" />
            </Panel>
            <Panel ux:Name="page2" HitTestMode="LocalBounds">
                <WhileString Value="{ReadProperty indicatorTarget}" Equals="page2indicator">
                    <Change mbTwo.IsSelected="true" />
                </WhileString>
                <MenuButton ux:Name="mbTwo" Label="Page 2" />
                <Clicked>
                    <Callback Handler="{navigate}" />
                </Clicked>
                <Panel ux:Name="page2indicator" Height="2" Alignment="Bottom" />
            </Panel>
        </Grid>
    </Panel>

    <Panel ux:Class="MenuButton" IsSelected="false">
        <string ux:Property="Label" />
        <bool ux:Property="IsSelected" />
        <WhileTrue Value="{ReadProperty IsSelected}">
            <Change theLabel.Opacity="1" Duration="0.3" />
        </WhileTrue>
        <Text ux:Name="theLabel" Value="{ReadProperty Label}" Alignment="Center" Color="#fff" FontSize="14" Opacity="0.5" />
    </Panel>

    <Router ux:Name="router" />

    <DockPanel>
        <MenuBar ux:Name="tabMenu" Dock="Top" router="router" />
        <PageControl ux:Name="nav">
            <Page ux:Name="page1" Background="#aaf">
                <WhileActive Threshold="0.5">
                    <Set tabMenu.indicatorTarget="page1indicator" />
                </WhileActive>
            </Page>
            <Page ux:Name="page2" Background="#afa">
                <WhileActive Threshold="0.5">
                    <Set tabMenu.indicatorTarget="page2indicator" />
                </WhileActive>
            </Page>
        </PageControl>
    </DockPanel>

</App>

Hello there,

apologise for late reply. i have created a simple project that explains how i break down the components.

https://drive.google.com/file/d/0BxujkUcSRVkbQWc2Uy1nbEFqVXc/view?usp=sharing

I am trying to make the tab menu bar to move as i am dragging the page. if it make any sense. Trying to achieve it by adding animation trigger (ActivatingAnimation) at page2 (under page control).

Meanwhile, I am going to checkout the solution you post above.

Thanks a lot for the prompt response

Hi Kesuma,

if you want to link the indicator movement to the swiping motion of the pages, then that currently is a bit tricky to achieve. Using the approach in my example is definitely the suggested way for the time being.

If you desperately need that linked motion, I could help you make it work - find me on the Slack community under the handle @uldis.