Vueify with vue-resource - laravel

I cannot seem to get vue-resource to work with vueify. I have defined one vue component which i am including in my main.js file.
import Vue from 'vue'
import MyComponent from './my-component.vue'
new Vue({
el: '#app',
components: {
myComponent: MyComponent
}
});
My vue component file looks like this:
<script>
import Vue from 'vue';
// import VueResource from 'vue-resource'
// Vue.use(VueResource);
export default {
template: '#my-component-template',
created: () => {
Vue.$http.get('/my/api/123',
data => {
console.log(data)
}, err => {
console.log("Error");
console.error(err);
}
);
}
}
</script>
In the current state, I receive this error:
Uncaught TypeError: Cannot read property 'get' of undefined
If I comment out the two lines concerning vue-resource in my component file, the error I receive turns like this:
Uncaught TypeError: Cannot redefine property: $url
package.json:
{
"private": true,
"scripts": {
"prod": "gulp --production",
"dev": "gulp watch"
},
"devDependencies": {
"bootstrap-sass": "^3.3.6",
"gulp": "^3.9.1",
"laravel-elixir": "^5.0.0",
"laravel-elixir-vueify": "^1.0.3",
"vue": "^1.0.25",
"vue-resource": "^0.8.0"
}
}
Gulpfile:
var elixir = require('laravel-elixir');
require('laravel-elixir-vueify');
elixir(function(mix) {
mix.browserify('main.js');
});
All existing answers on SO have not brought any results. Please help.

You should replace the $http with http:
import Vue from 'vue'
import VueResource from 'vue-resource'
Vue.use(VueResource)
export default {
created: () => {
Vue.http.get(...)
}
}
Also, it's a good practice to install the VueResource into the main file and then, we could use the this keyword as #Jeff said.
To achieve that, you should change the arrow function, because this refers to the global object:
// refers to the global object
created: () => {}
// refers to the Vue component
created () {
this.$http.get(...)
}

have you tried adding var VueResource = require('vue-resource'); in your root vue instance? also add Vue.use(VueResource).

Once you add the plugin in main.js using Vue.use(VueResource), it adds the $http attribute to all Vue instances. You don't need to re-do it in your component file. Then you just use this.$http:
created: () => {
this.$http.get('/my/api/123',
//...
);
}

Related

How to define globally external plugin with inertiajs + vue in laravel?

I want to use vue-device-detector in my project. in this plugin docs it says to register with Vue.use(device) so how am i supposed to do this with inertiajs createInertiaApp.
App Versions:
Laravel: 9.44.0
Vue: 3.2.31
inertiajs/inertia: 0.11.0
inertiajs/inertia-vue3: 0.6.0
I have tried .use(device) on createApp in app.js. getting this error in console
main.ts:87 Uncaught (in promise) TypeError: Cannot set properties of undefined (setting '$device').
Project is created with laravel jetstream starter kit.
EDIT 1:
Here is my app.js code. i am don't know how i can register plugin here. (Because inertia mount the app here so i suppose global plugin also needs to be registered here!!)
import './bootstrap';
import '../css/app.css';
import { createApp, h } from 'vue';
import { createInertiaApp } from '#inertiajs/inertia-vue3';
import { InertiaProgress } from '#inertiajs/progress';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from '../../vendor/tightenco/ziggy/dist/vue.m';
const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'Laravel';
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
setup({ el, app, props, plugin }) {
return createApp({ render: () => h(app, props) })
.use(plugin)
.use(ZiggyVue, Ziggy)
.mount(el);
},
});
InertiaProgress.init({ color: '#4B5563' });
PS: Thank you for reading my question, and please excuse any errors

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)
},
})

Laravel 8 Inertia HighCharts not being imported in the app.js

I am trying to integrate Highcharts with app.js in Laravel 8 with Vue and Inertia. I am trying to figure out how to pass HighchartsVue. I am trying to pass it to the use function for the createApp. However, I can't access it in the templates.
App.js
require("./bootstrap");
// Import modules...
import { createApp, h } from "vue";
import HighCharts from ""
import {
App as InertiaApp,
plugin as InertiaPlugin,
} from "#inertiajs/inertia-vue3";
const el = document.getElementById("app");
createApp({
render: () =>
h(InertiaApp, {
initialPage: JSON.parse(el.dataset.page),
resolveComponent: (name) => require(`./Pages/${name}`).default,
}),
})
.mixin({ methods: { route } })
.use(InertiaPlugin)
.mount(el);
My template that tries to access the Vue Template. I haven't included the entire template here.
Vue Template
<div>
<highcharts :options="indexOptions"></highcharts>
</div>
For a global registration:
After you have installed "highcharts-vue" using:
npm install highcharts-vue
Register it globally as a plugin in your app.js with:
import HighchartsVue from 'highcharts-vue'
Next register it as a plugin in your vue object with:
Vue.use(HighchartsVue)
Please see the documentation here for more detailed instructions (and how to register it locally in the component).
After installing, your app.js would look something like this:
require("./bootstrap");
// Import modules...
import { createApp, h } from "vue";
import HighchartsVue from 'highcharts-vue'
import {
App as InertiaApp,
plugin as InertiaPlugin,
} from "#inertiajs/inertia-vue3";
Vue.use(HighchartsVue);
const el = document.getElementById("app");
createApp({
render: () =>
h(InertiaApp, {
initialPage: JSON.parse(el.dataset.page),
resolveComponent: (name) => require(`./Pages/${name}`).default,
}),
})
.mixin({ methods: { route } })
.use(InertiaPlugin)
.mount(el);

How to use Vuetify 2 with Laravel

I haven't been able to integrate vuetify 2 successfully into a fresh installation of laravel. I understand that I have to install the vuetify-loader manually through webpack config since I'm not using Vue CLI 3. How do I do this in a laravel app?
I have tried modifying webpack config through webpack.mix.js by using code suggested by the vuetify documentation.
my webpack.mix.js looks like this:
const mix = require('laravel-mix');
//MYCODE
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin');
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css')
//MYCODE
.webpackConfig(webpack => {
return {
plugins: [
new VuetifyLoaderPlugin()
]
};
});
I have also tried changing APP_ENV in the .env file from "local" to "production".
When I npm run watch, I get this error:
/vuetifyapp/node_modules/webpack-cli/bin/cli.js:93
throw err;
^
Error: Cannot find module 'vuetify-loader/lib/plugin'
Some how I managed to integrate can't remember how. Hope this will help you.
https://github.com/avgkudey/LaraVuetify
After installing vuetify, you should upload / install your dependences, try to do :
npm install
And try after :
npm run watch
It should works
Just install the package:
npm install vuetify-loader -D
I made a gist with the files you need to change to a Laravel app to add a SPA environment using Vue. It will be a similar configuration to a Vue-CLI environment and you can install npm packages like vuetify normally.
basically you need to config these 4 files:
resources/js/app.js;
resources/js/App.vue;
resources/views/welcome.blade.php;
routes/web.php;
The 4 files are in here:
https://gist.github.com/marcelobbfonseca/9d1156ab3633793b765456c6a1f44bbc
If following this configuration your vue files will be in resources/js/ directory and you can run npm install vuetify. Add your vuetify.js file in resources/js/vuetify.js
This is an example vuetify.js config
resources/js/app.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import vuetify from './vuetify'
import Vuelidate from 'vuelidate'
Vue.use(Vuelidate)
Vue.config.productionTip = false
const app = new Vue({
router,
store,
vuetify,
render: h => h(App)
}).$mount('#app')
resources/js/vuetify.js
import Vue from 'vue'
import Vuetify from "vuetify"
import ptBr from './locale/ptBr.ts'
import 'vuetify/dist/vuetify.min.css'
import '#fortawesome/fontawesome-free/css/all.css'
Vue.use(Vuetify)
export default new Vuetify({
lang: {
locales: { ptBr },
current: 'ptBr',
},
icons: {
iconfont: 'fa'
},
theme: {
themes: {
light: {
primary: '#00551E',
secondary: '#3C8750',
tertiary: '#EEEEEE',
accent: '#69FFF1',
info: '#63D471',
success: '#4CAF50',
warning: '#FFC107',
error: '#FF5252',
danger: '#FF5252',
},
dark: {
primary: '#321321'
}
}
}
})
I wrote a short medium article for this environment configuration and unit testing
After many issues, I solve this on Laravel 8. Add to the v-app tag on component.
// resources/js/vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
Vue.use(Vuetify)
const opts = {}
export default new Vuetify(opts)
// resources/js/app.js
window.Vue = require('vue').default
import vuetify from './vuetify'
import store from './store/store'
Vue.component('g-home', require('./components/pages/GHome.vue').default)
const app = new Vue({
store,
vuetify,
el: '#app',
});
// Dependencies
{
"laravel-mix": "^6.0.6",
"sass": "^1.20.1",
"sass-loader": "^8.0.0",
"vue": "^2.5.17",
"vue-loader": "^15.9.5",
"vue-template-compiler": "^2.6.10",
"vuetify": "^2.4.3",
"vuetify-loader": "^1.7.1",
}
// webpack.mix.js
const mix = require('laravel-mix');
const webpack = require('./webpack.config');
Mix.listen('configReady', webpackConfig => {
// scss
const scssRule = webpackConfig.module.rules.find(
rule =>
String(rule.test) ===
String(/\.scss$/)
);
scssRule.oneOf.forEach(o => {
const scssOptions = o.use.find(l => l.loader === 'sass-loader').options
scssOptions.prependData = '#import "./resources/sass/_variables.scss";'
})
// sass
const sassRule = webpackConfig.module.rules.find(
rule =>
String(rule.test) ===
String(/\.sass$/)
);
sassRule.oneOf.forEach(o => {
const scssOptions = o.use.find(l => l.loader === 'sass-loader').options
scssOptions.prependData = '#import "./resources/sass/_variables.scss"'
})
})
mix.js('resources/js/app.js', 'public/js')
.js('resources/js/gift.js', 'public/js')
.vue()
.sass('resources/sass/pages/home.scss', 'public/css')
.sass('resources/sass/pages/gift.scss', 'public/css')
.webpackConfig(Object.assign(webpack))
.copyDirectory('resources/images/', 'public/images');
if (mix.inProduction()) {
mix.version();
};
// webpack.config.js
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin');
module.exports = {
plugins: [
new VuetifyLoaderPlugin(),
]
};

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