How to use Vuetify 2 with Laravel - 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(),
]
};

Related

Keep getting 'TypeError: Cannot call a class as a function' using Ziggy for Vue in Laravel

I have searched and searched and can't seem to find a solution to my problem.
I have taken the following steps:
\\Webpack.mix.js
const mix = require('laravel-mix');
const path = require('path');
mix.webpackConfig({
resolve: {
alias: {
ziggy: path.resolve('vendor/tightenco/ziggy/src/js/route.js'),
},
},
});
mix.js('resources/js/app.js', 'public/js').vue()
.postCss('resources/css/app.css', 'public/css', [
//
]);
mix.browserSync('127.0.0.1:8008');
And then in my app.js I have
\\app.js
require('./bootstrap');
import Vue from 'vue'
// Ziggy start here
import route from 'ziggy';
import { Ziggy } from './ziggy';
Vue.mixin({
methods: {
route: (name, params, absolute, config = Ziggy) => route(name, params, absolute, config),
},
});
// ziggy end here
import VendorLoginForm from './vue/components/vendors/auth/VendorLoginForm'
import VendorRegisterForm from './vue/components/vendors/auth/VendorRegisterForm'
import EditVendorProfile from './vue/components/vendors/profile/EditVendorProfile'
import { ValidationProvider, ValidationObserver, extend } from 'vee-validate/dist/vee-validate.full.esm';
extend("password", {
message: "{_field_} must be at least 10 characters long, contain one uppercase, one lowercase, and one number.",
validate: value => {
const strong_password = new RegExp(
"^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.{10,})"
); // regex to check our strong password
return strong_password.test(value); //Test the regex. Test function returns a true or false value.
}
});
import './scripts/validators'
Vue.component('ValidationProvider', ValidationProvider);
Vue.component('ValidationObserver', ValidationObserver);
Vue.component('extend', extend);
const app = new Vue({
el: '#vue-app',
components: { VendorLoginForm, VendorRegisterForm, EditVendorProfile }
});
I have ran the php artisan command to generate the ziggy.js and it seems to be working fine when I Ctrl+click it.
However when I got into my component to try to use route as below
mounted() {
console.log(this.route('home.page'))
},
I get the error:
app.js:51783 TypeError: Cannot call a class as a function
at _classCallCheck (app.js:3612)
at Route (app.js:3630)
at VueComponent.route (app.js:3345)
at VueComponent.mounted (app.cbfbd1ac1b8410f1ce58.hot-update.js:172)
at invokeWithErrorHandling (app.js:51749)
at callHook (app.js:54109)
at Object.insert (app.js:53032)
at invokeInsertHook (app.js:56234)
at VueComponent.patch [as __patch__] (app.js:56453)
at VueComponent.Vue._update (app.js:53838)
this was a nightmare when I was working with Ziggy at first time but I resolved my issue by
after creating ziggy.js in resources folder php artisan ziggy:generate
edit my webpack.mix.js file
const mix = require('laravel-mix');
const path = require('path');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.js('resources/js/app.js', 'public/js')
.vue()
.sass('resources/sass/app.scss', 'public/css');
mix.webpackConfig({
resolve: {
alias: {
ziggy: path.resolve('vendor/tightenco/ziggy/dist'),//Note we point to dist folder
},
},
});
then in App.js
import route from 'ziggy';
import {
Ziggy
} from './ziggy';
Vue.mixin({
methods: {
route: (name, params, absolute) => route(name, params, absolute, Ziggy)
}
});
then you can use route in your components
console.log(route("home"));

_plugins_vuetify__WEBPACK_IMPORTED_MODULE_8__.default is not a constructor

I had an issue upon installing vuetify to my project, I followed some solutions in some questions but still I had an issue.
Here is my vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
Vue.use(Vuetify)
const opts = {}
export default new Vuetify(opts)
App.js
import Vue from 'vue';
import Vuetify from '../plugins/vuetify';
Vue.use(Vuetify);
new Vue ({
router,
vuetify : new Vuetify(),
render: h => h(App),
}).$mount('#app');
webpack.mix.js
const mix = require('laravel-mix');
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin')
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
var webpackConfig = {
plugins: [
new VuetifyLoaderPlugin(),
new CaseSensitivePathsPlugin(),
],
}
mix.webpackConfig( webpackConfig );
mix.js('resources/js/app.js', 'public/js')
.vue()
.sass('resources/sass/app.scss', 'public/css');
You're close, but you're trying new up Vuetify when you should just be passing it in like this:
new Vue ({
router,
vuetify: Vuetify, // <-- simply set it like this
render: h => h(App),
}).$mount('#app');

Laravel Vuetify - Appends all css inline

I'm trying to use Vue on my laravel project.
And import vuetify for that project.
But it appends all css inline on the project.
My app.js is avobe:
window.Vue = require('vue');
//import Vuetify from 'vuetify'
import VueRouter from 'vue-router'
import {store} from './store/store'
import vuetify from './plugins/vuetify' // path to vuetify export
import 'vuetify/dist/vuetify.min.css' // Ensure you are using css-loader
import Master from './Master'
import router from './router'
Vue.use(VueRouter)
Vue.config.productionTip = false;
router.beforeEach((to, from, next) => {
if(to.matched.some(record => record.meta.requiresAuth)){
if(store.getters.loggedIn){
next()
}else{
next({name: 'login'})
}
}else{
if(store.getters.loggedIn){
next({name: 'dashboard'})
}else{
next()
}
}
})
// use the plugin
const app = new Vue({
el: '#app',
router: router,
store: store,
vuetify,
components: {Master},
template: "<Master />"
});
My webpack.mix.js:
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');
And here's the how code compiles itself:
How can I use vuetify codes on "blabla.css" file?
remove your vuetify.min.css in your app.js
and move that in your app.scss like this
#import '~vuetify/dist/vuetify.min.css';

vuetify.js.map: Source map error: SyntaxError

Im trying to study Laravel with VueJS using Homestead. I decided to use Vuetify in my study instead of Bootstrap by installing it throughnpm.
Here is my app.js:
import "material-design-icons-iconfont/dist/material-design-icons.css";
import "vuetify/dist/vuetify.min.css";
import Vue from "vue";
import Vuetify from "vuetify";
import App from "./components/App.vue";
import ExampleComponent from './components/ExampleComponent.vue';
import VueRouter from "vue-router";
import axios from "axios";
import VueAxios from "vue-axios";
Vue.use(Vuetify, VueRouter, axios, VueAxios);
const routes = [
{ path: "/", name: "Dashboard", component: ExampleComponent }
];
const router = new VueRouter({ mode: "history", routes: routes, linkExactActiveClass: "active" });
new Vue(Vue.util.extend({ router }, App)).$mount("#app");
But in my console log I'm getting this error:
Source map error: SyntaxError: JSON.parse: unexpected character at
line 1 column 1 of the JSON data Resource URL: http://xcy.dv/js/app.js
Source Map URL: vuetify.js.map
What am I missing here? I'm new to VueJS
By the help of Vuetify community, I found out that I need to include .sourceMaps() in my webpack.mix.js like this:
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css').sourceMaps();
It basically enable the source maps since it's disabled by default.
I had to update webpack.mix.js with
mix.webpackConfig({
output: {
chunkFilename: mix.inProduction() ? "js/prod/chunks/[name]?id=[chunkhash].js" : "js/dev/chunks/[name].js"
},
devtool: 'source-map' // Notice this
}).sourceMaps(); // And this
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');

Vueify with vue-resource

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',
//...
);
}

Resources