finally() not working in Vuejs another app - laravel-5

Recently I did this tutorial.
In this app I can successfully run a vuejs app and axios.then.catch.finally or this.form.then.catch.finally.
But I added npm to my old project that was recently upgraded to laravel 5.7.
In my app I can't add finally function. If i do, it says:
Uncaught TypeError: axios.post(...).then(...).catch(...).finally is not a function
My app.js:
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
// require('./bootstrap');
import Vue from 'vue'
window.Vue = Vue
window.axios = require('axios');
import { Form, HasError, AlertError } from 'vform'
window.Form = Form;
Vue.component(HasError.name, HasError)
Vue.component(AlertError.name, AlertError)
Vue.component('pagination', require('laravel-vue-pagination'));
//select 2
import vSelect from 'vue-select'
Vue.component('v-select', vSelect)
//sweet alert 1
import swal1 from 'sweetalert';
window.swal1 = swal1;
import swal from 'sweetalert2'
window.swal = swal;
const toast = swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000
});
window.toast = toast;
/**
* Next, we will create a fresh Vue ap
*
*
* plication instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('example-component', require('./components/ExampleComponent.vue'));
Vue.component('timetable-component', require('./components/TimetableComponent.vue'))
/* filter active and inactive */
Vue.filter('activeInactive', function (value) {
if(value==1){
return 'Active'
}else{
return 'Inactive'
}
})
const app = new Vue({
el: '#app',
data:{
},
methods:{
},
mounted(){
}
});
I think my app.js is exactly the same as the tutorial app.js for Form request.
Another thing is that in the tutorial he did not use axios import anywhere but he smoothly used it. But without import, I can't use axios.then.
How did he use it without importing axios?
How can I use finally with then.catch?
a componenet:
loadSite() {
axios
.get("/api/site/list")
.then(({ data }) => {
console.log(data);
this.siteList = data;
})
.catch(function(error) {
console.log(error);
}).finally(()=>{
});
},

As document, to make finally works, you need to add promise.prototype.finally
npm install axios promise.prototype.finally --save
and then
const axios = require('axios');
require('promise.prototype.finally').shim();
axios
.get('http://www.example.com/user')
.then((response) => {
console.log(response.data);
return response;
})
.finally(() => {
console.log('this will always be called');
});

I have the same issue, just solved it by includeing this file
<script src="https://polyfill.io/v3/polyfill.min.js?features=Promise.prototype.finally" defer></script>

Related

Laravel Vue3 - Passing Token and User info to Vue store

I'm creating a Laravel/Vue3 app and wanted to completely separate the Laravel router from the SPA router.
In order to achieve this I created a dashboard.blade.php file which contains the following content:
<x-app-layout>
<div id="app"></div>
</x-app-layout>
Vue then simply mounts on top of that div and the app is started.
My webpack.mix.js:
const mix = require("laravel-mix");
mix.ts("resources/js/app.ts", "public/js")
.vue({ version: 3 })
.postCss("resources/css/app.css", "public/css", [
require("postcss-import"),
require("tailwindcss"),
require("autoprefixer"),
]);
The app.ts file is also quite simple:
import { createApp } from 'vue';
import App from './App';
createApp(App).mount('#app');
Which is great, but my holdup is that for subsequent requests (via Axios), I will need the user token. How can I get this token/logged in user info to my Vue3 app?
I'm using Laravel Breeze for authentication (if that helps).
Thank you,
It turns out the answer was 'extremely' simple. I had to do nothing besides removing the comment tags on this line:
And add headers as follows in your axios config:
import axios from "axios";
import store from "../store";
const Axios = axios.create({
baseURL: process.env.APP_URL,
headers: { Accept: "application/json" },
});
Axios.interceptors.request.use(
(config) => {
store.commit("setLoader", true);
return config;
},
(error) => Promise.reject(error)
);
Axios.interceptors.response.use(
(response) => {
store.commit("setLoader", false);
return response;
},
(error) => Promise.reject(error)
);
export default Axios;
Subsequent axios calls have the token attached automatically.
You can find all the required information here. Love Laravel...

How to add loader in vue js

How to add Loading effect in VUE js plus Laravel.
This is a single page website in vuejs, i want to add loader when i change the route.
Means when i click to another router, it takes time to fetch data and show meanwhile i want to show loader. Or When i submit a form i takes time for submit meanwhile i want to add loader.
Means when i click to another router, it takes time to fetch data and show meanwhile i want to show loader. Or When i submit a form i takes time for submit meanwhile i want to add loader.
Means when i click to another router, it takes time to fetch data and show meanwhile i want to show loader. Or When i submit a form i takes time for submit meanwhile i want to add loader.
Means when i click to another router, it takes time to fetch data and show meanwhile i want to show loader. Or When i submit a form i takes time for submit meanwhile i want to add loader.
Help please in VUE js + Laravel
add this line of code in your app.js file
router.beforeEach((to, from, next) => {
// add loader
next()
})
router.afterEach(() => {
// terminate you loader
})
so Full file is
window.Vue = require('vue');
import VueRouter from 'vue-router';
import VueProgressBar from 'vue-progressbar'
window.Fire = new Vue();
Vue.use(VueProgressBar, {
color: 'rgb(143, 255, 199)', //normal color for progress bar
failedColor: 'red', //color for failed progress bar
height: '2px'//height of progress bar can be changed here
})
Vue.component(HasError.name, HasError)
Vue.component(AlertError.name, AlertError)
Vue.use(VueRouter);
window.Fire = new Vue();
let routes = [
{
path: '/',
name: 'posts',
component: post,
},
{
path: '/general',
name: 'dashboard',
component: Dashboard,
},
];
let router = new VueRouter({
routes // short for `routes: routes`
});
router.beforeEach((to, from, next) => {
// add loader
VueProgressBar .start();
next()
})
router.afterEach(() => {
// terminate you loader
VueProgressBar.finish();
})
const app = new Vue({
el: '#app',
router,
data: {},
methods: {}
});
window.Fire = new Vue();
If you are requesting while browsing through the pages, the loader can work accordingly.
<script>
export default {
data: () => ({
loaderIsActive: false,
items: null,
}),
mounted() {
this.fetch();
},
methods: {
async fetch() {
this.loaderIsActive = true;
this.items = await axios.post('YOUR API');
this.loaderIsActive = false;
}
}
}
In this way you can use it.

Vue.js router view no components?

I am trying to make a vue SPA using vuex, vue-router & laravel for backend. I was separating our data on our app.js to try to reduce clutter and keep our code neat. When everything on one page it works as intended, loading the routes in the router. But when we separate the code to make it more modular into: app.js, boostrap.js, routes.js, and store.js
The components aren't loading in our router-view and we are able to see our RouterLink
app.js
// Require the bootstrapper
require('./bootstrap');
// Grab imports
import Store from './store';
import Router from './routes';
// Views
import App from './views/App';
// Create the application
const app = new Vue({
el: '#heroic',
components: { App },
store: Store,
router: Router
});
boostrap.js
// Imports
import Vue from 'vue';
import Axios from 'axios';
import Swal from 'sweetalert2';
// Add to window
window.Vue = Vue;
window.Axios = Axios;
// Add Axios headers
window.Axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.Axios.defaults.headers.common['Authorization'] = 'Bearer ' + 'token';
window.Axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
routes.js
// Imports
import Vue from 'vue';
import VueRouter from 'vue-router';
import Store from './store';
// Set to use
Vue.use(VueRouter);
// Views
import Hello from './views/Hello';
import Home from './views/Home/';
import UserIndex from './views/UserIndex';
// Create our routes
const routes = [
{
path: '/',
name: 'home',
component: Home,
},
{
path: '/hello',
name: 'hello',
component: Hello,
},
{
path: '/users',
name: 'users.index',
component: UserIndex,
}
];
// Create the router
const router = new VueRouter({
mode: 'history',
routes: routes,
scrollBehavior (to, from, saved) {
if (saved) {
return saved;
}
return { x: 0, y: 0};
}
});
// Before every request
router.beforeEach((to, from, next) => {
});
// After every request
router.afterEach((to, from, next) => {
});
// Export
export default router;
hello.vue
<template>
<div class="row row-cards row-deck">
<div class="col-lg-4 col-md-6">
<p>Hello World!</p>
</div>
</div>
</template>
store.js
// Imports
import Vue from 'vue';
import Vuex from 'vuex';
import PersistedState from 'vuex-persistedstate';
import Cookie from 'js-cookie';
// Set use
Vue.use(Vuex);
// Create our store
const store = new Vuex.Store({
state: {
auth: [{
id: 1,
username: '',
motto: '',
rank: 1,
permissions: [],
token: ''
}],
users: [],
},
mutations:{
},
actions: {
},
getters: {
}
});
// Export
export default store;
The expected result is that when I visit the "/hello" route it would show the information that says "Hello world!" that is within the Vue file specified as the component in the routes section of the router. Instead using my Vue DevTools I get the following with no Hello world on the page.
https://i.pathetic.site/chrome_99Mbxf7f0c.png
My guess is the router is stuck waiting for the beforeEach (and also possibly afterEach) hook to be resolved. You need to call next().
Also unrelated, but if you’re using modules then you shouldn’t need to assign stuff on window.

laravel + vue router cannot get parameters from url

I try to get parameters from url
let's say url contains:
localhost:8000/blog?q=hello
I want to grab hello to trigger function call
What I had declare in app.js in laravel webpack:
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const router = new VueRouter({
mode: 'history',
routes: []
})
const app = new Vue({
router
});
export default app;
In blog page, I try to extract the parameter from url
new Vue ({
el: "#blog-content",
},
mounted: function() {
q = this.$route.query.q
console.log(q)
}
)
I npm run dev to compile and run the blog page it show error:
TypeError: Cannot read property 'query' of undefined
what is wrong? I am sure that Vue Router is properly installed in the application.
I think that the blog page that you use is not correct.
You recreate another Vue instance and in that case that new instance doesn't have a router passed to it. So I think that's why this.$router is undefined.
Also you don't pass the view Component to your router so it doesn't know what to look for with the specific url.
Here's your app.js file corrected
import VueRouter from 'vue-router';
Vue.use(VueRouter);
import Blog from './views/Blog';
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/blog',
name: 'blog',
component: Blog
},
]
});
The blog view page template : views/Blog.vue
<template>
<div class="wrapper">
My blog page
</div>
</template>
<script>
export default {
data() {
return {
myvariable : ''
}
},
mounted() {
let q = this.$route.query.q;
console.log(q);
},
};
</script>
Now it should works correctly :)
Edit : Also you don't need to export the app variable in your app.js
Remove the following line export default app; at the end of the file

Vue <template> in a .vue file with Lodash

In my .vue file within my template section I have:
<a v-bind:href="'javascript:artist(\'' + _.escape(artist) + '\')'">
which is using the Lodash function _.escape. This generates a string of errors the first of which is:
[Vue warn]: Property or method "_" is not defined on the instance but referenced during
render.
However in the same file in the script section of the component I am happily and successfully using a range of Lodash functions.
This is a Laravel app and in my app.js file I have this code:
require('./bootstrap');
window.Vue = require('vue');
import VueRouter from 'vue-router';
window.Vue.use(VueRouter);
import lodash from 'lodash';
Object.defineProperty(Vue.prototype, '$lodash', { value: lodash });
import SearchHome from './components/search.vue';
const routes = [
{
path: '/',
components: {
searchHome: SearchHome
}
},
]
const router = new VueRouter({ routes })
const app = new Vue({ router }).$mount('#app')
Can anyone please help me?
Try to use a computed value instead. This will improve readability.
Avoid complex operation in a binding.
<a :href="artistLink">
And in the script
import _ from 'lodash'
export default {
computed: {
artistLink () {
return 'javascript:artist(\'' + _.escape(this.artist) + '\')'
}
}
}

Resources