I'm trying to create a global helper function via Vue mixin on a Laravel Inertia project to no avail:
//app.js
Vue.mixin({
methods: {
myFunction() {
return 'Returnign from myFunction';
},
},
});
new Vue({
...
}).$mount(app);
.
//MyComponent.vue
console.log(myFunction()); // ReferenceError: myFunction is not defined
On a standalone Vue.JS project, this works. Maybe there's something behind the scene in Inertia that prevents the mixin from loading. Can somebody help me understand why this is happening?
Thank you.
you need () on your function
Vue.mixin({
methods: {
myFunction() {
return 'Returnign from myFunction';
},
},
});
and then you missed this before your mixin function
console.log(this.myFunction());
You need to add the function in the mixin of the createInertiaApp method in your app.js file.
For instance:
createInertiaApp({
resolve: (name) => require(`./Pages/${name}.vue`),
setup ({ el, app, props, plugin }) {
return createApp({ render: () => h(app, props) })
.use(plugin)
.mixin({
methods: {
myFunction: () => {
return 'Returning from myFunction';
}
}
})
.mount(el)
}
})
Is it possible to write middleware in Nuxt to be triggered after mounting any page.
If I use the following middleware
export default function ({ app }) {
if (!process.server) {
app.$somePluginFunction()
}
}
it is triggered when navigating to that page, thus before mounting it. That is not what I am looking for.
I also know you can use the mounted() hook on an individual page, which is what I want, but I don't want to write the same mounted() hook to every page in my app manually. How can I do this?
There is many way to trigger a function before route change:
First use in default layout
// layout/default.vue
export default {
watch: {
$route () {
console.log('route changed', this.$route)
}
},
}
Second use before route:
https://router.vuejs.org/guide/advanced/navigation-guards.html#in-component-guards
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})
Third write plugin like this:
how to write global router-function in nuxt.js
And write mixin like this :
Run function AFTER route fully rendered in Nuxt.js
I am playing around with VueJS and trying to make an api call from within a component:
var postView = {
props: ['post'],
template: '<li>{{ post.title }}</li>',
url: 'https://jsonplaceholder.typicode.com/posts',
data: function () {
return {
results: []
}
},
mounted() {
axios.get(url).then(response => {
this.results = response.data
})
},
ready: function () { },
methods: {}
}
Vue.component('postitem', postView);
var app = new Vue({
el: '#app',
data: {},
ready: function () { },
methods: {}
})
I get the following error:
[Vue warn]: Property or method "results" is not defined on the
instance but referenced during render.
I am wondering what the best approach is to make api calls from within a component and display it on a HTML page. I learned that a component’s data option must be a function, but I'm not sure what the error related to 'results' means.
First of all you should consider using vue single file components. They are great for splitting your functionality.
Vue requests guide
You can watch the whole playlist for complete vue guide. The link is to the video that explains api calls in vue.
i think that error for (this)
you can do like that:
var vm = this;
axios.get(url).then(response => {
vm.results = response.data
})
We using Vue2 in a website, not an SPA, so we use single file components punctually to improve the user experience.
Ssr works with this code in entry_server.js, we can call this file from the command line for example node ssr-bundle.js or from an express APP:
// entry_server.js
import Test from 'components/Test.vue';
const app = new Vue({
render: h => (Test, {
props: {}
})
});
export default function(context) {
return new Promise((resolve, reject) => {
resolve(app);
});
};
This is a example component:
// Test.vue
<template>
<div>
{{apidata}}
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
apidata: []
};
},
beforeCreate() {
axios.get('/api/v1/versions.json', {params: {card_id: 274}}).then(response => {
this.apidata = response;
console.log('loadData!!!');
console.log(response);
});
},
};
</script>
When we need fetch data from an API the component render ok but it doesn't show this data, the render doesn't wait for API request.
We found many SSR examples and doc using vuex and router for this, but, how to make SSR with a single file component prefetch data from API and without vuex or router?
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,
}