Basics: Getting started w vue-router

I’m trying to use native vue-router but it’s not working yet.

Ref project: https://github.com/aadamsx/fp-admin

I’m getting the following error:

Uncaught TypeError: Router.map is not a function

Here is the code:

// router.js

// import { Router } from 'meteor/akryum:vue-router2';
import Router from 'vue-router'

import Index from '/imports/client/views/public/Index.vue';
import Page from '/imports/client/views/public/Page.vue';
import FirstForm from '/imports/client/views/public/FirstForm.vue';

// Not found
import NotFound from '/imports/client/views/public/NotFound.vue';

Router.map({
  // Not found handler
  '*': {
    component: {
        template:
        '<div>' +
        '<h1>Not Found</h1>' +
        '</div>'
    }
  },
  '/': {
    component: Index
  },
  '/page': {
    component: Page
  },
  '/first-form': {
    component: FirstForm
  },
  '/not-found': {
    component: NotFound
  }
});

And code from Meteor.startup:

// app.js

import '/imports/client/router.js';
import Vue from 'vue';
import VueMeteorTracker from 'vue-meteor-tracker'
// import { Router, nativeScrollBehavior } from 'meteor/akryum:vue-router2';
import Router from 'vue-router'
import AppLayout from '/imports/client/views/AppLayout.vue';

const router = new Router({
  mode: 'history',
  scrollBehavior: nativeScrollBehavior,
});

Meteor.startup(() => {
  Vue.use(VueMeteorTracker);
  Vue.use(Router);

  new Vue({
      router: router.start(),
      render: h => h(AppLayout),
  }).$mount('app');
});

My original code that used akryum:vue-router2 worked fine and looked like this:

import { Router } from 'meteor/akryum:vue-router2';

import Index from '/imports/client/views/public/Index.vue';
import Page from '/imports/client/views/public/Page.vue';
import FirstForm from '/imports/client/views/public/FirstForm.vue';

// Not found
import NotFound from '/imports/client/views/public/NotFound.vue';

Router.configure(router => {
  router.addRoutes([{
    path: "/",
    name: "Index",
    components: {
      default: Index,
    }
  }, {
    path: "/page",
    name: "Page",
    components: {
      default: Page,
    }
  }, {
    path: "/first-form",
    name: "FirstForm",
    components: {
      default: FirstForm,
    }
  }, {
    path: "/not-found",
    name: "NotFound",
    components: {
      default: NotFound,
    }
  },]);
});

router.map() is from old vue-router versions. Now, you have to declare the routes in an array that you pass to the router constructor: example.

1 Like

Thanks @akryum. But now, no errors, but nothing renders:

// app.js

import Vue from 'vue';
import VueMeteorTracker from 'vue-meteor-tracker'
import VueRouter from 'vue-router'
import AppLayout from '/imports/client/views/AppLayout.vue';
import Routes from '/imports/client/router.js';

const router = new VueRouter({
  Routes
});

Meteor.startup(() => {
  Vue.use(VueMeteorTracker);
  Vue.use(VueRouter);

  const app = new Vue({
      router: router,
      render: h => h(AppLayout),
  }).$mount('app');
});

// router.js

import Page from '/imports/client/views/public/Page.vue';
import FirstForm from '/imports/client/views/public/FirstForm.vue';

// 1. Define route components.
// These can be imported from other files
const NotFound = { template: '<div><h1>Not Found</h1></div>' }
const Index = { template: '<div>Home</div>' }

// 2. Define some routes
// Each route should map to a component. The "component" can
// either be an actual component constructor created via
// Vue.extend(), or just a component options object.
export const routes = [
  { path: '*', component: NotFound }, // Not Found handler
  { path: '/', component: Index },
  { path: '/page', component: Page },
  { path: '/first-form', component: FirstForm  }
];

The order of the routes matters now, so you have to put your ‘*’ route at
the end of the array.

1 Like

This works for me:

// router.js

import FirstForm from '/imports/client/views/public/FirstForm.vue';

const NotFound = { template: '<div><h1>Not Found</h1></div>', name: 'NotFound' }
const Index = { template: '<div>Home</div>', name: 'Index' }

export const routes = [
  { path: '/', name: 'Index', component: Index },
  { path: '/first-form', name: 'FirstForm', component: FirstForm }//,
];

// app.js

import Vue from 'vue';
import VueRouter from 'vue-router';

import VueMeteorTracker from 'vue-meteor-tracker';

import AppLayout from '/imports/client/views/AppLayout.vue';
import { routes } from '/imports/client/router.js';

Vue.use(VueMeteorTracker);
Vue.use(VueRouter);

const router = new VueRouter({
  mode: 'history',
  routes: routes
});

Meteor.startup(() => {
  const app = new Vue({
    router: router,
    render: h => h(AppLayout),
  }).$mount('app');
});

// applayout.vue

<template>
  <div>
    <router-link to="/">Home</router-link>
    <router-link to="/first-form">FirstForm</router-link>
    <router-view></router-view>
  </div>
</template>

My bad, the routes had an uppercase R and it shouldn’t.

1 Like

Whats a way to router-link within blaze?

Within Blaze, I’d use standard <a> elements instead of router-links.

but that means that page will reload, and you have to use href (may brake link in future.)

You’re doing that within Blaze because of the legacy app?

Did you try that?

import {Vue} from 'meteor/akryum:vue';
import Widget from '/imports/ui/Widget.vue';

Template.vue_demo.rendered = function() {
  var vm = new Vue({
    el: '#vue-demo',
    template: '<div><widget></widget></div>',
    components: {
      Widget
    }
  });
}

source: https://github.com/Akryum/meteor-vue-blaze

Yea, but then I’d have to also import vue router in there. I suppose vue is lightweight enough to instantiate a new vue instance for every blaze link :stuck_out_tongue:. Although no less ugly way of doing it might be keeping flow-router.

PS keeping blaze around is not that bad as there is atmospherejs.com with tight integration for meteor.