0
votes

Writing in NativeScript-Vue for Android, I am trying to render a component based on button taps. I am using this this plugin to wrap the app in a global SideDrawer for quick navigation. I use buttons within the SideDrawer for viewing components. Here is what my App.vue looks like:

<template>
    <Frame>
        <Page actionBarHidden="true">
            <GlobalDrawer>
                <template slot="content">
                    <Label class="drawer-header" text="Drawer"/>
                    <Button class="drawer-button" text="Home" @tap="currentComponent = 'Home'" />
                    <Button class="drawer-button" text="Info" @tap="currentComponent = 'InfoPage'" />
                    <Button class="drawer-close-button" @tap="$drawer.close()">Close</Button>
                </template>
                <template slot="frame">

                    <ContentView>

                        <component v-for="component in pagesArray" v-show="component === currentComponent" :is="component" v-bind:key="component" />

                    </ContentView>
                </template>
            </GlobalDrawer>
        </Page>
    </Frame>
</template>

<script>

import Home from './pages/Home.vue';
import InfoPage from './pages/InfoPage.vue';

export default {
    data () {
        return {
            pagesArray: ['Home', 'InfoPage'],
            currentComponent: 'Home'
        };
    },
    components: {
        Home, 
        InfoPage
    }    
}
</script>

Here is the code in Home.vue, the default component I try to render:

<template>
    <Page>
        <navigation-bar />

        <GridLayout>
            <Label class="info" horizontalAlignment="center" verticalAlignment="center">
                <FormattedString>
                    <Span class="fa" text.decode="&#xf135; "/>
                    <Span :text="message"/>
                </FormattedString>
            </Label>
        </GridLayout>
    </Page>
</template>

<script>
import NavigationBar from '../components/NavigationBar.vue';

    export default {
        computed: {
            message() {
                return "Test Homepage";
            }
        },
        components: {
            NavigationBar
        }
    };
</script>

If I directly use the <home /> component within <ContentView /> it displays fine, but when trying to display it dynamically, I get a blank page; no errors. Any thoughts on this?

I run the app on a connected Samsung Galaxy S7 using the NativeScript CLI. NativeScript-vue version: ^2.4.0.

Edit [01.20.20]: Detailed explanation on how I solved it.

Read about it here: https://nativescript-vue.org/en/docs/routing/manual-routing/

In Application.vue, my GlobalDrawer looks like this:

<GlobalDrawer >
            <template class="global-drawer" slot="content">
                <ScrollView orientation="vertical" scrollBarIndicatorVisible="true" height="100%">
                    <StackLayout orientation="vertical">
                        <Label class="drawer-header" text="Menu"/>
                        <Button class="drawer-button" text="Home" ref="homeButton" @tap="homePageTap"/>
                        <Button class="drawer-button" text="System Oversight" @tap="infoPageTap" />
                        <Button class="drawer-button" text="Companies" @tap="companiesPageTap" />
                        <Button class="drawer-button" text="Calendar" @tap="calendarPageTap" />
                        <Button class="drawer-close-button" @tap="$drawer.close()">Close</Button>
                        <Label class="drawer-footer" text="By Bouvet" />
                    </StackLayout>
                </ScrollView>
            </template>
            <template slot="frame">

                    <frame-hub />

            </template>
</GlobalDrawer>

The methods-section contains the @tap-methods:

methods: { 
    homePageTap(args) {
        this.$navigateTo(Home, { frame: "main-frame" });
        this.$drawer.close();
    },
    infoPageTap(args) {
        this.$navigateTo(InfoPage, { frame: "main-frame" });
        this.$drawer.close();
    },
    companiesPageTap(args) {
        this.$navigateTo(CompaniesPage, { frame: "main-frame" });
        this.$drawer.close();
    },
    calendarPageTap(args) {
        this.$navigateTo(CalendarPage, { frame: "main-frame" });
        this.$drawer.close();
    }
},

The < frame-hub > is a component (FrameHub.vue), looking like this:

<template>
    <Page actionBarHidden="true">
        <Frame id="main-frame">
            <home />
        </Frame>
    </Page>
</template>

<script>

import Home from './../pages/Home';
import InfoPage from './../pages/InfoPage.vue';
import CompaniesPage from './../pages/CompaniesPage.vue';
import CalendarPage from './../pages/Calendar.vue';

export default {
    components: {
        Home, 
        InfoPage,
        CompaniesPage,
        CalendarPage
    }  
}
</script>

The @tap-methods in Application.vue changes the components that are renderered within the"main-frame"-element in FrameHub.vue. This way the GlobalDrawer is always on top, while the user is free to switch between pages.

I hope this helps anyone having the same issue. Also I'm sure this solution can be improved. Though I'm not currently working on this, but please let me know about improvements.

1
Do you want to show only 1 component based on the mouse click? If so why do you use a for then? - Steven
Any updates, news? - Steven
Hi @Steven! Thank you for the suggestion. I ended up dropping this solution and instead putting a 'hub'-component in the template named 'frame'. Then in this component I had a <Frame> with an id, which I then referenced in the @tap-handlers of the GlobalDrawer-buttons, using it to render components in. It works very well and I can use the frame-id globally. I got the idea from this tutorial: youtube.com/watch?v=exE1WfPvAX0 I am still curious to why the first attempt did not work, but I suspect it has to do with how the plugin is structured. Also excuse my late response. - kristoffer sylte dahl
No problem I'm glad to hear that you fixed the issue! - Steven
I'm in the same issue but unfortunately the explanation is still vague. Can you include some kind of example? It could be much easier to follow. I really appreciate if anybody can help in this direction. - hgc2002

1 Answers

2
votes

Creator of nativescript-vue-global-drawer plugin here.

The frame slot of GlobalDrawer contains a Frame element (here) to control navigation inside the drawer as stated here, which means the slot accept only Page elements.