This is my component:
const Vue = require("vue/dist/vue.js");
const qs = require("querystring");
module.exports = Vue.component("Page",function(resolve){
console.log($route);
let id = this.$route.params.id;
fetch("/getPage.json",{
method:"POST",
body:qs.stringify({
id
})
}).then(r=>r.json())
.then(j=>{
console.log(j);
resolve({
template:`<h1>`+JSON.stringify(j)+"</h1>"
});
})
});
And this is my router:
const router = new VueRouter({
mode:"history",
routes:[
{
path:"/",
component:Home
},
{
path:"/me",
component:Me
},
{
path:"/create-page",
component:createPage
},
{
path:"/p/:id",
component:Page
}
]
});
Vue.use(VueRouter);
When i run this app i get:
ReferenceError: $route is not defined
I tried using this.$route but it's not working. I'm using an arrow function. When i do this it works:
const Vue = require("vue/dist/vue.js");
module.exports = Vue.component("Page",function(resolve){
resolve({
template:`<h1>{{$route.params.id}}`
});
});
Please help me figure out how to fix this.
in your main vue app
new Vue(...)
you have to use vue-router first
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
...
new Vue(...)
...
and the go ahead with route declaration
you forgot to add router in Vue instance
in you main.js or app.js or index.js (entry point)
const app = new Vue({
router
})
documentation
You should NOT use arrow functions
data: function() {
return {
usertype: this.$route.params.type
};
},
This worked for me.
Related
I'm having an issue with a linting error in a vue.js project. The error that I get looks like this:
/Users/mikecuddy/Desktop/coding/data_science_projects/statues/client/src/store/modules/common.js
4:1 error Dependency cycle via #/store/index:4 import/no-cycle
I have no idea how to get rid of this error. I tried renaming files, using this.$router and this.$store with no luck. Here is some of my code:
router -> index.js:
The data path is the main one I want to get to. Notice that I have the store import files commented out - that does get rid of the dependency error but then I have issues with doing something like:
this.$store.state.common.loginFlag
as opposed as importing the store and doing this:
store.state.common.loginFlag
import Vue from 'vue';
import VueRouter from 'vue-router';
// import store from '../store/index.js';
// import store from '#/store/index';
import Home from '../views/Home.vue';
Vue.use(VueRouter);
const routes = [
{
path: '/data',
name: 'Data',
component: () => import('../views/Data.vue'),
beforeEnter: (to, from, next) => {
if (this.$store.state.common.loginFlag === false) {
next('/login');
} else {
next();
}
},
beforeRouteLeave: (to, from, next) => {
if (this.$store.state.common.loginFlag === false) {
next('/login');
} else {
next();
}
},
},
];
const router = new VueRouter({
routes,
});
export default router;
store/modules/common.js:
import Vue from 'vue';
import Vuex from 'vuex';
import axios from 'axios';
import router from '../../router';
Vue.use(Vuex);
const data = {
userNotFound: false,
passwordNoMatch: false,
loginFlag: false,
};
const getters = {
userNotFound: (state) => state.userNotFound,
passwordNoMatch: (state) => state.passwordNoMatch,
loginFlag: (state) => state.loginFlag,
};
const actions = {
login: ({ commit }, { payload }) => {
const path = 'http://localhost:5000/login';
axios.post(path, payload)
.then((res) => {
if (res.data.login_flag) {
commit('session/setUserObject', res.data.user, { root: true });
commit('setLoginFlag', res.data.login_flag);
// Tried this:
router.push{ name: 'Data' }
// As well as trying this:
this.$router.push({ name: 'Data' });
}
commit('setNoPasswordMatch', res.data.Password_no_match);
commit('setUserNotFound', res.data.Not_found);
})
.catch((error) => {
console.log(error);
});
},
};
// I have mutations but did not think they'd be needed
const mutations = {};
export default {
namespaced: true,
state: data,
getters,
actions,
mutations,
};
In the common.js file I've tried commenting out:
import router from '../../router';
and that seemed to work - got the Dependency cycle error to go away and in the router/index.js file I was able to get to the route but had an issue with this.$store.state.common.loginFlag when I commented out import store from '#/store/index'; If I leave in the import of: import store from '#/store/index';
then I get the dependency cycle error.
I've also found some help at these other stack pages:
TypeError: Cannot read properties of undefined (reading '$router') vuejs
dependency cycle detected import/no-cycle
I will say that I hate using linters and that's what's giving me the problem here.
Here is the code for store/index.js:
import Vue from 'vue';
import Vuex from 'vuex';
import common from './modules/common';
import session from './modules/session';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
common,
session,
},
});
Looks like the reason for the dependency cycle here is when you are importing router setup in the store module, and the router in turn imports the whole store. It's okay to use store in router, but try to move routing/redirect logic (these lines):
// Tried this:
router.push{ name: 'Data' }
// As well as trying this:
this.$router.push({ name: 'Data' });
from /modules/common.js to the component or global router hook level, so you avoid router import in the store module.
I've been following the VueMastery courses and stumbled upon an unexpected problem I cannot seem to resolve myself.
Without using the Global Router Guards the URL updates normally on both modes. But as soon as I add the following hooks to my router (router/index.js) I get no errors whatsoever, but the URL won't update anymore:
router.beforeEach((routeTo, routeFrom, next) => {
NProgress.start();
next();
});
router.afterEach((routeTo, routeFrom, next) => {
NProgress.done();
next();
});
Using:
#vue/cli 4.2.3
vue-router 3.1.5
My complete router (router/index.js) file contains the following script:
import Vue from "vue";
import VueRouter from "vue-router";
import EventList from "../views/EventList.vue";
import store from "#/store/index";
import NProgress from "nprogress";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "event-list",
component: EventList
},
{
path: "/event/create",
name: "event-create",
component: () =>
import(/* webpackChunkName: "event-create" */ "../views/EventCreate.vue")
},
{
path: "/event/:id",
name: "event-show",
component: () =>
import(/* webpackChunkName: "event-show" */ "../views/EventShow"),
props: true,
beforeEnter(routeTo, routeFrom, next) {
store.dispatch("event/fetchEvent", routeTo.params.id).then(event => {
routeTo.params.event = event;
next();
});
}
}
];
const router = new VueRouter({
mode: "history",
routes
});
router.beforeEach((routeTo, routeFrom, next) => {
NProgress.start();
next();
});
router.afterEach((routeTo, routeFrom, next) => {
NProgress.done();
next();
});
export default router;
And is imported and used in my main.js:
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
// Automatic Global Component Registraton
import upperFirst from "lodash/upperFirst";
import camelCase from "lodash/camelCase";
// NProgress
import "nprogress/nprogress.css";
const requireComponent = require.context(
// The relative path of the components folder
"./components",
// Whether or not to look in subfolders
false,
// The regular expression used to match base component filenames
/Base[A-Z]\w+\.(vue|js)$/
);
requireComponent.keys().forEach(fileName => {
// Get component config
const componentConfig = requireComponent(fileName);
// Get PascalCase name of component
const componentName = upperFirst(
camelCase(
// Gets the file name regardless of folder depth
fileName
.split("/")
.pop()
.replace(/\.\w+$/, "")
)
);
// Register component globally
Vue.component(
componentName,
// Look for the component options on `.default`, which will
// exist if the component was exported with `export default`,
// otherwise fall back to module's root.
componentConfig.default || componentConfig
);
});
Vue.config.productionTip = false;
new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
What could possibly cause the URL to not update anymore? I tried using the default hash mode but the same problem occurred. The URL's just won't update when clicking the router-links.
There should be an error telling you that
TypeError: next is not a function
because next is not defined in afterEach, since that is the end of the routing middleware chain. If you remove the next from afterEach, it should work again:
router.afterEach((routeTo, routeFrom) => {
NProgress.done();
});
Here is a link to the docs
I'm getting warnings during tests running on my new Vue.js project. Wherever a component uses the router either in the template as a <router-link> or programatically as this.$router.push('/');
The tests are passing but logging these warnings:
ERROR LOG: '[Vue warn]: Error in render: "TypeError: Cannot read property 'resolve' of undefined"
found in
---> <RouterLink>
<Root>'
I'm using Vue2 and the project is based on the webpack project generated by the cli tool.
My unit test index.js:
import Vue from 'vue';
import VueNativeSock from 'vue-native-websocket';
import Router from 'vue-router';
Vue.use(Router);
Vue.use(VueNativeSock, process.env.WEBSOCKET_ADDR, { format: 'json', reconnection: true });
Vue.config.productionTip = false;
const testsContext = require.context('./specs', true, /\.spec$/);
testsContext.keys().forEach(testsContext);
const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/);
srcContext.keys().forEach(srcContext);
My main.js:
import Vue from 'vue';
import VueNativeSock from 'vue-native-websocket';
import VueHead from 'vue-head';
import App from './App';
import router from './router';
Vue.config.productionTip = process.env.NODE_ENV === 'production';
Vue.use(VueNativeSock, process.env.WEBSOCKET_ADDR, { format: 'json', reconnection: true });
Vue.use(VueHead);
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App },
head: {
link: [
{ rel: 'icon', href: '/static/favicon-32x32.png', sizes: '32x32', type: 'image/png' },
],
},
});
Any idea what I'm missing to get these warnings to go away?
A basic test might look like this:
import Vue from 'vue';
import ViewDTCs from '#/components/ViewDTCs';
describe('ViewDTCs.vue', () => {
const Constructor = Vue.extend(ViewDTCs);
const vm = new Constructor().$mount();
ViewDTCs.$socket = new WebSocket(process.env.WEBSOCKET_ADDR);
it('has a created hook', () => {
expect(typeof ViewDTCs.created).to.equal('function');
});
it('should render page', () => {
expect(vm.$el.textContent).to.contain('Retrieving DTCs');
});
});
It looks like your routes might not be set up anywhere in your test environment. If you're using Karma and Avoriaz or Vue Test Utils, I've been able to test components that contain routes like this:
import { mount } from 'vue-test-utils'
import router from 'src/router' // path to your router
import MyComponent from 'src/components/MyComponent'
describe('MyComponent.vue', () => {
let wrapper
beforeEach(() => {
wrapper = mount(MyComponent, {
router: router
})
})
it('has a created hook', () => {
expect(typeof wrapper.created).to.equal('function')
})
...
})
hey guys i am trying to do a request inside my action on the vuex side, and i get this error:
Cannot read property '$http' of undefined
i set my vue-resource this way inside my main.js file:
import Vue from 'vue'
import VueResource from 'vue-resource'
import VueRouter from 'vue-router'
import App from './App.vue'
import {routes} from './routes';
import {store} from './store/store';
import VModal from 'vue-js-modal'
Vue.use(VModal)
Vue.use(VueResource);
Vue.use(VueRouter);
const router = new VueRouter({
routes
});
new Vue({
el: '#app',
store,
router,
render: h => h(App)
})
then on the store:
addStyle(state,newStyleObj) {
console.log(newStyleObj);
var vm = this;
this.$http.post('http://localhost:16339/api/Styles/PostStyle/', newStyleObj)
.then(response => {
state.tableStyles = response.body;
console.log(state.tableStyles)
console.log(response.body)
}, error => {
console.log(error);
});
}
any help?
import axios from 'axios'
import Vue from 'vue'
import Vuex from 'vuex'
const axiosInstance = axios.create({
baseURL: '',
withCredentials: true,
})
Vue.prototype.$axios = axiosInstance
Vuex.Store.prototype.$axios = axiosInstance
This works for me.
Now you can access via this.$axios in Vue and Vuex.
You can access Vue instance from the store using this._vm.
this._vm.$http.post()
Here is a proper explanation of the problem that $http is not accessible within vuex https://stackoverflow.com/a/42571288/6355502
The state can only be altered in mutations. NOT in actions. Just commit a mutation from inside of the action to alter the state.
I tried the same last night and got error messages that forced me to do the async fetching in actions which trigger mutations. You cannot do async operations in mutations and you cannot alter the state in actions, so you have to split the code.
// in actions
addStyle ({ commit, state }, newStyleObj) {
console.log(newStyleObj);
var vm = this;
this.$http.post('http://localhost:16339/api/Styles/PostStyle/', newStyleObj)
.then(response => {
commit("setTableStyles", response.body);
console.log(state.tableStyles)
console.log(response.body)
}, error => {
console.log(error);
});
}
// in mutations
setTableStyles(state, payload){
state.tableStyles = payload; // or state.tableStyles.push(...payload) if tableStyles is an Array
}
Outside vue instance (store in this case) use Vue.http (without the dollar sign), inside instance use this.$http.
You can find more on github.
access to axios with Vue.prototype.$http
login({commit}, loginFormData) {
return new Promise((resolve, reject) => {
commit('auth_request');
Vue.prototype.$http({url: '/user/login', data: loginFormData, method: 'POST'})
.then(resp => {
const token = resp.data.data.token;
const user = resp.data.data.profile;
localStorage.setItem('token', token);
localStorage.setItem('user', JSON.stringify(user));
Vue.prototype.$http.defaults.headers['Authorization'] = 'Bearer ' + token;
this.state.user = JSON.parse(localStorage.getItem('user')) || '';
this.state.token = localStorage.getItem('token') || '';
commit('auth_success', {token, user});
resolve(resp)
})
.catch(err => {
commit('auth_error');
localStorage.removeItem('token');
localStorage.removeItem('user');
reject(err)
})
})
},
Try Accessing vue Properties by this way this._vm.$yourDesiredPropertyName
For example this._vm.$http etc
It worked for me .
You can access all the properties which are properly registered to vue instance
Im creating a custom plugin that encapsulates a bunch of authentication functionality with vuex and vue-authenticate.
The problem im having is figuring out the correct way to load and install the module into VueJS, im not sure if its my webpack or vuejs knowledge that is lacking but so far I have the following
/node_modules/plugin/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import routes from './routes'
import store from './vuex/store'
import EventBus from './bus/eventBus'
import config from './config'
import ping from './vuex/modules/apiArchitect/ping/store'
import auth from './vuex/modules/apiArchitect/auth/store'
import user from './vuex/modules/apiArchitect/user/store'
Vue.use(Vuex)
Vue.use(EventBus)
const store = new Vuex.Store({
modules: {
ping,
user,
auth
},
strict: true
})
let apiArchitect = {}
apiArchitect.install = function (Vue, options) {
Vue.prototype.$apiArchitect = store,
Vue.prototype.$apiArchitect.$config = config
Vue.prototype.$apiArchitect.$routes = routes
if (typeof window !== 'undefined' && window.Vue) {
window.Vue.use(apiArchitect)
}
}
export default apiArchitect
/src/main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import apiArchitect from 'vue-apiarchitect'
import addRouteGuards from 'vue-apiarchitect/src/addRouteGuards'
Vue.config.productionTip = false
Vue.config.env = process.env.NODE_ENV
Vue.use(router)
Vue.use(apiArchitect)
console.log(apiArchitect)
addRouteGuards(router)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
So far I am able to import the plugin and run the install hook with Vue.use(apiArchitect) I can access this.$apiArchitect in my App.vue.
The problem I have is that the plugin provides some auth routes stored in $apiArchitect.routes these routes need to be merged with the routes provided by router. If I try access $apiArchitect.routes in main.js I get an 'undefined' error I can only access them after vue has been instantiated. If I actually try console.log apiArchitect in main.js all I see is an object containing an install function none of the plugin i've provided which makes me belive its not installing correctly.
Does anyone know how i can access the apiArchitect.$routes property in main.js or a better way of achieving this?
Thanks
You can add routes dynamically with router.addRoutes() since 2.2.x.
The argument must be an Array using the same route config format with
the routes constructor option.
For example, you can use addRoutes in created hook of the root component:
// your plugin
const myPlugin = {
install: function(Vue, options) {
Vue.prototype.$myPlugin = {
routes: [{
path: '/myplugin', component: options.myComponent
}]
}
}
}
// components
const testComponent = { template: '<p>Component called by plugin route</p>' }
const Home = { template: '<p>Default component</p>' }
// router
const router = new VueRouter({
routes: [{
path: '/', component: Home
}]
})
Vue.use(VueRouter)
Vue.use(myPlugin, { myComponent: testComponent })
new Vue({
el: '#app',
router,
created() {
this.$router.addRoutes(this.$myPlugin.routes); // dinamically add routes
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.0/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<button #click="$router.push('/')">Home</button>
<button #click="$router.push('/myplugin')">Custom</button>
<router-view></router-view>
</div>