Vue <template> in a .vue file with Lodash - laravel-5

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) + '\')'
}
}
}

Related

Default Persistent Layout In Laravel + Inertia + Vite

In the previous way of setting up inertia in a laravel app, I could tweak the resolve property in the `createInertiaApp function from:
{
...,
resolve: name => import("./Pages/${name}"),
...
}
To
{
...,
resolve: name => {
const page = require("./Pages/${name}").default
if(!page.layout) {
page.layout = DefaultLayoutFile
}
},
...
}
To allow me manually pass a default layout file to be used in pages.
But with Vite becoming the default asset bundler and according to the docs, I must use a resolvePageComponent function which takes in import.meta.glob as a second argument to instruct Vite which files to bundle.
Problem here is the import gets returned from this resolvePageComponent so I cannot access the default object like I normally will from a require function.
So I have not been able to attach a default layout file to imported pages.
Has anyone been able to find a workaround for this?
Assuming you imported your default layout file like this (remember to not use # in imports anymore as only relative paths work for static analysis reasons):
import DefaultLayoutFile from './Layouts/DefaultLayoutFile.vue'
You can use the following code to get default layout working with Inertia and Vite:
resolve: (name) => {
const page = resolvePageComponent(
`./Pages/${name}.vue`,
import.meta.glob("./Pages/**/*.vue")
);
page.then((module) => {
module.default.layout = module.default.layout || DefaultLayoutFile;
});
return page;
},
[UPDATE 2022-08-01]
Since this is still receiving views, I though it would be useful to show how to get the # working in imports in Vite.
Require path below your imports in vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '#vitejs/plugin-vue';
const path = require('path')
And then add resolve into your config below:
export default defineConfig({
resolve:{
alias:{
'#' : path.resolve(__dirname, './src')
},
},
})
Now # will point to your Laravel root and you can import components dynamically from anywhere:
For example import LayoutTop from '#/Layouts/LayoutTop.vue'
will now point to
/resources/js/Layouts/LayoutTop.vue
Remember that Vite needs the .vue extension when importing Vue SFC files.
The async await version of the accepted answer
resolve: async name => {
const page = await resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob("./Pages/**/*.vue"));
page.default.layout ??= DefaultLayoutFile;
return page;
},
This worked from me using the vite with inertia preset
import { createApp, h } from 'vue'
import { createInertiaApp } from '#inertiajs/inertia-vue3'
import { resolvePageComponent } from 'vite-plugin-laravel/inertia'
import DefaultLayout from '#/views/layouts/default.vue'
import SimpleLayout from '#/views/layouts/simple.vue'
import UserLayout from '#/views/layouts/user.vue'
createInertiaApp({
resolve: (name) => {
const page = resolvePageComponent(
name,
import.meta.glob('../views/pages/**/*.vue'),
DefaultLayout
);
page.then((module) => {
if (name.startsWith('auth.')) module.layout = SimpleLayout;
if (name.startsWith('user.')) module.layout = [DefaultLayout, UserLayout];
});
return page
},
setup({ el, app, props, plugin }) {
createApp({ render: () => h(app, props) })
.use(plugin)
.mount(el)
},
})

vue v-select array of object not showing in select option

laravel project with vue.i install all thing in app js to work v-select, i don't know anyhting is missing in installation or not.if something is missing tell me that or somthing is wrong in v-select tag please help if anyone is experienced such a thing
on app.js-----------------------------------------------------------------
require('./bootstrap');
window.Vue = require('vue');
import VueRouter from 'vue-router'
import Cat from './components/dashboard/category/Category.vue';
import Sub from './components/dashboard/sub-category/sub-category.vue';
import Dash from './components/dashboard/Dashboard.vue';
import VueToast from 'vue-toast-notification';
import Vuetify from 'vuetify';
import 'vuetify/dist/vuetify.min.css';
import VModal from 'vue-js-modal';
// import Vue from 'vue';
import vSelect from 'vue-select';
import 'vue-select/dist/vue-select.css';
// Import one of available themes
import 'vue-toast-notification/dist/theme-default.css';
import { Form, HasError, AlertError } from 'vform';
window.Form = Form;
// import {routers} from './routers';
Vue.use(Vuetify)
Vue.use(VueToast);
Vue.use(VueRouter);
Vue.use(VModal);
// Vue.use(vSelect)
Vue.component('v-select', vSelect)
const routes = [
{ path: '', component: Dash },
{ path: '/category', component: Cat },
{ path: '/sub-category', component: Sub },
]
const router = new VueRouter({
routes
})
const app = new Vue({
el: '#app',
router,
vuetify: new Vuetify()
});
on component--------------------------------------------------------------------------------
<v-select v-model="select" :items="categories" label="Select" item-text="name" item-value="id" return-object> </v-select>
export default {
data(){
return {
form: new Form({
name:'',
imgUrl:'',
remember: false
}),
categories:[],
select: 'Select',
}
},
mounted(){
this.getCategories()
},
methods:{
getCategories(){
axios.get('sub-category')
.then(res => (
res.data.forEach((value, index) => {
this.categories.push(value);
})
));
}
}
}
Should the items property in the v-select tag not be called options? Source: https://vue-select.org/guide/options.html#options-prop

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

finally() not working in Vuejs another app

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>

Resources