vuejs: Is there a way to access router.go() inside a component? - vue.js

I want to call router.go inside a component
currently i have set window.router = router // so the code works
index.js
const App = Vue.extend(require('./views/app.vue'))
router.start(App, '#app')
window.router = router // I don't want to set this global variable
navbar.vue
methods: {
search () {
window.router.go({
name: 'search',
query: { q: this.query }
})
}
}
what i am looking for is something like, this.$router.go
navbar.vue
methods: {
search () {
this.$router.go({
name: 'search',
query: { q: this.query }
})
}
}
Thanks and really appreciate some help

For vue-router 2.x
this.$router.push('path')
For vue-router 1.x
this.$route.router.go('path')

Related

How I can get Vue component data while using script setup

I need to rewrite
this code
export default Vue.extend<Props>({
functional: true,
render(h, { props, slots, data }) {
const { href, external, target, type, button } = props;
const slot = slots().default;
console.log(data);
....
to Vue 3 Composition script setup,
So I managed to get
<script setup lang="ts">
import {h, useSlots} from 'vue';
const props = defineProps<Props>();
const slots = useSlots();
...
But how I can get data ?
from this part -> render(h, { props, slots, data }) {
data should contain domProps if have such.. etc
console.log(data);
{
{
attrs: {
target: '_self',
href: 'https://example.com',
button: true
},
class: [
'X-button',
{
'X-button--': false,
'X-button--size-auto': true
}
]
}
Thanks in advance
If you still need this,
useSlots().default() returns the data for the slots, including the DOM props.

how to call a function in vue when navigating way from route?

I am trying to call a function that clears local storage when the user navigates away from the current page. How would I accomplish this? I tried using the destroyed() lifecycle hook but it did not work. Would using beforeRouteLeave() be a good solution and how would I implement that in my routes file?
my route:
{
path: "/success",
name: "Success",
component: () =>
import("../views/Success.vue"),
},
my hook on the success page as it currently stands:
destroyed() {
window.localStorage.removeItem("intent");
},
what i tried with beforeRouteLeave
beforeRouteLeave: function(to, from, next) {
window.localStorage.removeItem("intent");
next();
},
my mounted hook
let intent = window.localStorage.getItem(intent);
// const product = window.localStorage.getItem(product);
axios
.get("http://localhost:5000/pay/confirm", {
params: {
intent: intent
}
})
.then(res => {
console.log(res.data.status);
if (res.data.status == "succeeded") {
console.log(res.data.status);
this.confirmPayment();
} else {
this.paid = false;
}
console.log(this.item);
});
},
You can try set (global/page) watcher for you, which will be do something when you route object changed
watch:{
$route function(to, from){
// do something
}
}
mayby you can use the beforeDestroy() hook instead of the destroyed() hook.

Vue.js Pass plugin variable towards custom component

I am a novice in Vue.js and I am trying to create my first plugin, something very simple, to be able to call it from my application as follows:
app.js
Vue.use(Pluginify, { option1: 1, option2: 2 });
The problem I am having is the following, I have in my index.js file of my plugin, a variable called configuration, this variable is the second argument that I passed to the Vue.use function, the problem is that I need to pass that variable to a custom component I'm creating, but can't. Please could you help me, this is the structure I have so far:
index.js
import Vue from 'vue';
import Plugin from './Plugin';
import { isObject } from 'lodash';
export const instance = new Vue({
name: 'Plugin',
});
const Pluginify = {
install(Vue, configuration = {}) { // This variable here, I need to pass it to the ```Plugin.vue``` component
Vue.component('plugin', Plugin);
const pluginify = params => {
if (isObject(params)) {
instance.$emit('create', params);
}
};
Vue.pluginify = pluginify;
Vue.prototype.$pluginify = pluginify;
}
};
export default Pluginify;
I have a component called Plugin that is empty, but I need it to contain the configuration object in order to use its values ​​in the future.
Plugin.vue
<template>
</template>
<script>
import { instance } from './index';
export default {
name: 'Plugin',
mounted() {
instance.$on('create', this.create);
},
methods: {
create(params) {
}
}
};
</script>
<style scoped>
</style>
Thank you very much in advance
Ok, I have achieved it as follows:
index.js
const Pluginify = {
install(Vue, configuration = {}) {
/**
* Default plugin settings
*
* #type {Object}
*/
this.default = configuration;
....
So in my Plugin.vue component:
import * as plugin from './index';
So I can call in any method of my component the configuration parameters as follows:
...
mounted() {
console.log(plugin.default.option1);
},
...
I hope I can help anyone who gets here with a similar question.
It seems like this listener is added after the create event already fired
mounted() {
instance.$on('create', this.create);
},
You could use a global variable in your plugin like this ...
Vue.prototype.$pluginifyConfig = configuration;
and then you can call it with this.$pluginifyConfig in the plugin, or anywhere else.
But that pollutes the global scope
Maybe this could help:
const Plugin = {
template: '<div>Plugin</div>',
data() {
return {
a: 'a data'
};
},
mounted() {
console.log(this.a);
console.log(this.message);
}
};
const Pluginify = {
install(Vue, options) {
Vue.component('plugin', {
extends: Plugin,
data() {
return {...options}
}
});
}
};
Vue.use(Pluginify, {message: 'hello, world!'});
new Vue({
el: '#app'
});

Pass data through router to other component in vue

I am trying to pass data through router. My code is working but it shows data in url. I don't want that like as POST method.url should like /data-list . Also I want to catch passing value from component. Here I did not use vuex . Actually my job is to show message that task is done based on this data. I am using Laravel for backend. Thanks in advance
1st component
axios.post("/request/data", dataform).then(function (resp) {
app.$router.push({ path: "/data-list/" + resp.data.success });
});
routes
{
path: '/data-list/:message?',
name: 'dataList',
component: dataList,
meta: {
auth: true
}
},
Another component. Here I want to catch
mounted() {
var app = this;
app.message = app.$route.params.message;
}
So if I understand correctly, you are fetching data in some component and then you are doing a router-push to dataList component.
You want to access the data in dataList component.
Since you always want the route to be /dataList, do this in your routes file
{
path: '/data-list', //removing dynamic tag.
name: 'dataList',
component: dataList,
meta: {
auth: true
}
},
Then in the component where you do router push, add a handleClick like so.
handleClick() {
let data = {
id: 25,
description: "pass data through params"
};
this.$router.push({
name: "dataList", //use name for router push
params: { data }
});
}
}
Then in your dataList component you can access the data passed in the mounted like so :
mounted() {
let data = this.$route.params.data;
console.log("data is", data);
}
Working implementation attached below.
You can push router data in router like this.
this.$router.push({
name: "dataList",
params: { data: resp.data },
});
and in the routes you can define your route as
{
path: "/dataList",
name: "dataList",
props: true,
meta: { title: "Data list" },
component: () => import("path to datalist component")
},
and in the DataList.vue you can use props to get the data
export default {
props:['data'],
mounted(){
alert(this.data);
}
}

Update VueJs component on route change

Is there a way to re-render a component on route change? I'm using Vue Router 2.3.0, and I'm using the same component in multiple routes. It works fine the first time or if I navigate to a route that doesn't use the component and then go to one that does. I'm passing what's different in props like so
{
name: 'MainMap',
path: '/',
props: {
dataFile: 'all_resv.csv',
mapFile: 'contig_us.geo.json',
mapType: 'us'
},
folder: true,
component: Map
},
{
name: 'Arizona',
path: '/arizona',
props: {
dataFile: 'az.csv',
mapFile: 'az.counties.json',
mapType: 'state'
},
folder: true,
component: Map
}
Then I'm using the props to load a new map and new data, but the map stays the same as when it first loaded. I'm not sure what's going on.
The component looks like this:
data() {
return {
loading: true,
load: ''
}
},
props: ['dataFile', 'mapFile', 'mapType'],
watch: {
load: function() {
this.mounted();
}
},
mounted() {
let _this = this;
let svg = d3.select(this.$el);
d3.queue()
.defer(d3.json, `static/data/maps/${this.mapFile}`)
.defer(d3.csv, `static/data/stations/${this.dataFile}`)
.await(function(error, map, stations) {
// Build Map here
});
}
You may want to add a :key attribute to <router-view> like so:
<router-view :key="$route.fullPath"></router-view>
This way, Vue Router will reload the component once the path changes. Without the key, it won’t even notice that something has changed because the same component is being used (in your case, the Map component).
UPDATE --- 3 July, 2019
I found this thing on vue-router documentation, it's called In Component Guards. By the description of it, it really suits your needs (and mine actually). So the codes should be something like this.
export default () {
beforeRouteUpdate (to, from, next) {
// called when the route that renders this component has changed,
// but this component is reused in the new route.
// For example, for a route with dynamic params `/foo/:id`, when we
// navigate between `/foo/1` and `/foo/2`, the same `Foo` component instance
// will be reused, and this hook will be called when that happens.
// has access to `this` component instance.
const id = to.params.id
this.AJAXRequest(id)
next()
},
}
As you can see, I just add a next() function. Hope this helps you! Good luck!
Below is my older answer.
Only saved for the purpose of "progress"
My solution to this problem was to watch the $route property.
Which will ended up you getting two values, that is to and from.
watch: {
'$route'(to, from) {
const id = to.params.id
this.AJAXRequest(id)
}
},
The alternate solution to this question handles this situation in more cases.
First, you shouldn't really call mounted() yourself. Abstract the things you are doing in mounted into a method that you can call from mounted. Second, Vue will try to re-use components when it can, so your main issue is likely that mounted is only ever fired once. Instead, you might try using the updated or beforeUpdate lifecycle event.
const Map = {
data() {
return {
loading: true,
load: ''
}
},
props: ['dataFile', 'mapFile', 'mapType'],
methods:{
drawMap(){
console.log("do a bunch a d3 stuff")
}
},
updated(){
console.log('updated')
this.drawMap()
},
mounted() {
console.log('mounted')
this.drawMap()
}
}
Here's a little example, not drawing the d3 stuff, but showing how mounted and updated are fired when you swap routes. Pop open the console, and you will see mounted is only ever fired once.
you can use just this code:
watch: {
$route(to, from) {
// react to route changes...
}
}
Yes, I had the same problem and solved by following way;
ProductDetails.vue
data() {
return {
...
productId: this.$route.params.productId,
...
};
},
methods: {
...mapActions("products", ["fetchProduct"]),
...
},
created() {
this.fetchProduct(this.productId);
...
}
The fetchProduct function comes from Vuex store. When an another product is clicked, the route param is changed by productId but component is not re-rendered because created life cycle hook executes at initialization stage.
When I added just key on router-view on parent component app.vue file
app.vue
<router-view :key="this.$route.path"></router-view>
Now it works well for me. Hopefully this will help Vue developers!
I was having the same issue, but slightly different. I just added a watch on the prop and then re-initiated the fetch method on the prop change.
import { ref, watch } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import Page from './content/Page.vue';
import Post from './content/Post.vue';
const props = defineProps({ pageSlug: String });
const pageData = ref(false);
const pageBodyClass = ref('');
function getPostContent() {
let postRestEndPoint = '/wp-json/vuepress/v1/post/' + props.pageSlug;
fetch(postRestEndPoint, { method: 'GET', credentials: 'same-origin' })
.then(res => res.json())
.then(res => {
pageData.value = res;
})
.catch(err => console.log(err));
}
getPostContent();
watch(props, (curVal, oldVal) => {
getPostContent();
});
watch(pageData, (newVal, oldVal) => {
if (newVal.hasOwnProperty('data') === true && newVal.data.status === 404) {
pageData.value = false;
window.location.href = "/404";
}
});
router - index.js
{
path: "/:pageSlug",
name: "Page",
component: Page,
props: true,
},
{
path: "/product/:productSlug",
name: "Product",
component: Product,
},
{
path: "/404",
name: "404",
component: Error404,
}