Skip to content

$navigator.path not updated correctly if using class style Vue components #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
superalex opened this issue Mar 26, 2020 · 9 comments
Closed
Labels

Comments

@superalex
Copy link
Contributor

I have a sample where I'm using your plugin to navigate to two different components and show the path in the $navigator.path and it works perfectly:

app.js

import Vue from 'nativescript-vue';

import App from './components/App';

import Navigator from 'nativescript-vue-navigator'
import { routes } from './routes'
Vue.use(Navigator, { routes })

new Vue({
    render: h => h(App),
}).$start();

routes/index.js

import C1 from '~/components/c1'
import C2 from '~/components/c2'

export const routes = {
    '/route-1': {
        component: C1,
    },
    '/route-2': {
        component: C2,
    }
}

compontents/App.vue

<template>
    <GridLayout class="App" rows="*, auto">
        <ContentView row="0">
            <Navigator defaultRoute="/route-1" />
        </ContentView>

        <nav row="1" />
    </GridLayout>
</template>

<script>
    import nav from "./nav";
    export default {
        components: {
            nav
        },
        data() {
            return {};
        }
    };
</script>

components/c1.vue

<template>
    <Page class="page">
        <StackLayout>
            <Label text="Component 1" />
        </StackLayout>
    </Page>
</template>

<script>
    export default {};
</script>

components/c2.vue

<template>
    <Page class="page">
        <StackLayout>
            <Label text="Component 2" />
        </StackLayout>
    </Page>
</template>

<script>
    export default {};
</script>

If I use class Style Vue components with in the components:

components/c2.vue

<template>
    <Page class="page">
        <StackLayout>
            <Label text="Component 2" />
        </StackLayout>
    </Page>
</template>

<script>
    @Component
    export default class C2 extends Vue { };
</script>

Then $navigator.path isn't correctly updated and keeps the initial value.

@rigor789
Copy link
Member

I have no idea what's causing that with class components.

Can you create a watcher and watch $navigator.path see if changes get triggered?
$navigator itself is just a Vue instance, nothing magic going on there.

@superalex
Copy link
Contributor Author

I tried the watcher but nothing get triggered.

I added some console logs and i found that if I do:

  Vue.mixin({
    mounted() {
      console.log("Mounted", this.$options.__path)
      // attach the current path if set to the root element
      if (this.$options.__path) {
        this.$el.setAttribute('__path', this.$options.__path)
      }
    },
  })

And navigate to a "normal" component the console shows:

JS: 'Mounted' undefined
JS: 'Mounted' '/wishlist'
JS: 'Mounted' undefined

But with a class style component just:

JS: 'Mounted' undefined
JS: 'Mounted' undefined
JS: 'Mounted' undefined

It seems class style component doesn't receive properly the $options.__path

@rigor789
Copy link
Member

rigor789 commented Mar 26, 2020

Can you share the compiled source of a class component? (it should be in platforms folder somewhere in a bundle.js if I remember correctly). It's usually a long transpiled file with all your code - but the component should be there somewhere. Might give us a clue why $options.__path is not set.

@superalex
Copy link
Contributor Author

Sure!

The compiled source for:

<script lang='ts'>
import { Component, Vue } from "vue-property-decorator";
@Component
export default class C1 extends Vue {
}
</script>

Should be:

var C1 = /** @class */ (function (_super) {
    Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"])(C1, _super);
    function C1() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    C1 = Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__decorate"])([
        vue_property_decorator__WEBPACK_IMPORTED_MODULE_1__["Component"]
    ], C1);
    return C1;
}(vue_property_decorator__WEBPACK_IMPORTED_MODULE_1__["Vue"]));
/* harmony default export */ __webpack_exports__["default"] = (C1);

@rigor789
Copy link
Member

Yeah, that's way different from regular js components...

If you edit the source of the navigator, specifically this line:

routes[path].component.__path = path

If you add

if(routes[path].component.options) {
  routes[path].component.options.__path = path
}

Does that make a difference?

(ref: vuejs/vue-class-component#337)

@superalex
Copy link
Contributor Author

superalex commented Mar 26, 2020

¡Yes!, with that change the Watch works and $navigator.path is correctly updated :)

Thank you veru much! 🕺

@rigor789
Copy link
Member

rigor789 commented Mar 26, 2020

Great! Mind opening a PR with the change?

Perhaps add a comment above the if block explaining why this is needed, something like

// this is required to attach the path to vue-class-components. see #31
if(routes[path].component.options) {
  routes[path].component.options.__path = path
}

@superalex
Copy link
Contributor Author

superalex commented Mar 26, 2020 via email

superalex added a commit to superalex/nativescript-vue-navigator that referenced this issue Mar 27, 2020
@github-actions
Copy link

🎉 This issue has been resolved in version 1.1.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

2 participants