How to define globally external plugin with inertiajs + vue in laravel? - 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

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

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 add bootstrap-vue module Laravel Jetstream with InertiaJS?

How can I work with bootstrap-vue on Laravel, using Laravel 8, Jetstream and InertiaJS?
import Vue from 'vue'
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
// Import Bootstrap an BootstrapVue CSS files (order is important)
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
// Make BootstrapVue available throughout your project
Vue.use(BootstrapVue)
// Optionally install the BootstrapVue icon components plugin
Vue.use(IconsPlugin)
I don't know where and how to add the app.js file.
app.js:
require('./bootstrap');
// Import modules...
import { createApp, h } from 'vue';
import { App as InertiaApp, plugin as InertiaPlugin } from '#inertiajs/inertia-vue3';
import { InertiaProgress } from '#inertiajs/progress';
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);
InertiaProgress.init({ color: '#4B5563' });
This is my css.js.
Here add the CSS libraries.
#import 'tailwindcss/base';
#import 'tailwindcss/components';
#import 'tailwindcss/utilities';
#import 'bootstrap/dist/css/bootstrap.css';
#import 'bootstrap-vue/dist/bootstrap-vue.css';
As I can see from your configuration. You are using InertiaJS with Vue3. Right now, BootStrap-Vue components only works with Vue2 (info). So you need first to downgrade InertiaJS from Vue3 to Vue2. With npm
npm uninstall #inertiajs/inertia-vue3 vue #vue/compiler-sfc vue-loader
npm install #inertiajs/inertia-vue vue vue-template-compiler vue-loader
It seems weird to uninstall and reinstall vue and vue-loader, but is the easiest way to properly update the dependencies.
Now you need to put in your app.js.
import Vue from 'vue';
import { createInertiaApp } from '#inertiajs/inertia-vue';
import BootstrapVue from 'bootstrap-vue';
Vue.use(BootstrapVue);
createInertiaApp({
resolve: (name) => require(`./Pages/${name}`),
setup({ el, app, props }) {
new Vue({
render: (h) => h(app, props),
}).$mount(el);
}
});
The app.css does not need any modification. Unless you need to modify and theme Bootstrap, in that case you must change to SASS.

Ziggy - Inertia js vue app NOT mounted AT ALL if we import route from 'ziggy' in app.js

I am working on a projet where it uses Laravel , ziggy ,inertia and vue.
i can not use ziggy in vue as suggested by thier doc.
here is my complete app.js
NB i can see the expected Ziggy.js file in /js/ziggy.js
//___________app.js________________
require('./bootstrap')
import Vue from 'vue'
import VueMeta from 'vue-meta'
import PortalVue from 'portal-vue'
import { App, plugin } from '#inertiajs/inertia-vue'
import { InertiaProgress } from '#inertiajs/progress/src'
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
Vue.use(BootstrapVue)
Vue.use(IconsPlugin)
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import { mixins } from 'vue-chartjs'
import route from 'ziggy';// the vue app is not mounted at all if i import the route from 'ziggy' and there is no error in console.;
import { Ziggy } from './ziggy';
Vue.mixin({
methods: {
route: (name, params, absolute, config = Ziggy) => route(name, params, absolute, config),
},
});
//Vue.config.productionTip = false
//Vue.mixin({ methods: { route: window.route } })
Vue.use(plugin)
Vue.use(PortalVue)
Vue.use(VueMeta)
InertiaProgress.init()
let app = document.getElementById('app')
new Vue({
metaInfo: {
titleTemplate: (title) => title ? `${title} - SSSYT` : 'your partner'
},
render: h => h(App, {
props: {
initialPage: JSON.parse(app.dataset.page),
resolveComponent: name =>
import (`./Pages/${name}`).then(module => module.default),
},
}),
}).$mount(app)
and here is the error i get in colnsole
Uncaught TypeError: Cannot read property 'prototype' of undefined
at Object.inherits (app.js:124712)
at Object.<anonymous> (app.js:68991)
at Object../node_modules/irc/lib/irc.js (app.js:69342)
at __webpack_require__ (app.js:64)
at Object../node_modules/ziggy/index.js (app.js:140181)
at __webpack_require__ (app.js:64)
at Module../resources/js/app.js (app.js:141504)
at __webpack_require__ (app.js:64)
at Object.0 (app.js:142081)
at __webpack_require__ (app.js:64)
```
For import route from 'ziggy'; to work, you need to alias 'ziggy' to the correct location in your Mix file.
Add this to your webpack.mix.js:
const path = require('path');
// Mix v6
mix.alias({
ziggy: path.resolve('vendor/tightenco/ziggy/dist'),
});
// Or, for Mix v5
mix.webpackConfig({
resolve: {
alias: {
ziggy: path.resolve('vendor/tightenco/ziggy/dist'),
},
},
});
See the section about this in the Ziggy docs for more details.

Vuetify in Storybook gets error: undefined is not an object (evaluating 'this.$vuetify.theme.dark')

I'm trying to use Vuetify in Storybook with costume setup. The .Storybook/config.js looks like:
import { configure, addDecorator } from '#storybook/vue';
import 'vuetify/dist/vuetify.css';
import Vue from 'vue';
import Vuetify from 'vuetify';
Vue.use(Vuetify, {
theme: {
dark: {
primaryTypColor: '#232B2B',
productCardTitle: '#7E7F80'
},
light: {
primaryTypColor: '#232B2B',
productCardTitle: '#7E7F80'
},
},
});
addDecorator(() => ({
template: '<v-app><story/></v-app>',
}));
configure(require.context('../stories', true, /\.stories\.js$/), module);
I'm getting the error: undefined is not an object (evaluating 'this.$vuetify.theme.dark') why is that?
It is because you haven't injected the global vuetify object in the Vue.js context. You can do so with a decorator.
In your example it looks like you only need to add the Vuetify that you imported to the addDecorator function as a parameter.
A complete example for storybook versions below 6, here is how:
import Vue from 'vue';
import vuetify from '#plugins/vuetify'
Vue.use(vuetify)
addDecorator(() => ({
template: '<v-app><story/></v-app>',
vuetify,
}));
For storybook version 6:
import vuetify from '#plugins/vuetify'
import Vue from 'vue'
Vue.use(vuetify)
export const decorators = [
() => ({
template: '<v-app><story/></v-app>',
vuetify
}),
]

Resources