InertiaJS with Laravel & Vue2: Cannot redefine property: $inertia - laravel

I'm not sure why I am getting this error:
Uncaught TypeError: Cannot redefine property: $inertia
at Function.defineProperty (<anonymous>)
at Object.install (app.js:108)
at Function.Vue.use (app.js:233295)
at Module../resources/js/app.js (app.js:246829)
at __webpack_require__ (app.js:20)
at Object.0 (app.js:253385)
at __webpack_require__ (app.js:20)
at app.js:84
at app.js:87
and this warning:
Registering the Inertia Vue plugin via the "app" component has been deprecated. Use the new "plugin" named export instead.
import { plugin } from '#inertiajs/inertia-vue'
Vue.use(plugin)
I followed the docs as closely as I could. I'm using Vue2 and Laravel 8. I can't find anyone with the same issues anywhere. The error claims that 'App' is no longer used, but the docs for Vue2 use it in their example. I'm confused, what am I missing?
Here is my code:
resources/js/app.js:
import { App, plugin } from '#inertiajs/inertia-vue'
import Vue from 'vue'
Vue.use(App)
Vue.use(plugin)
InertiaProgress.init()
Vue.component('drafts', require('./pages/Drafts').default)
const el = document.getElementById('app')
new Vue({
render: (h) =>
h(App, {
props: {
initialPage: JSON.parse(el.dataset.page),
resolveComponent: (name) =>
import(`./pages/${name}`).then((module) => module.default),
},
}),
}).$mount(el)
resources/views/app.blade.php:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'AppealMaker') }}</title>
<!-- Styles -->
<link href="{{ mix('css/app.css') }}" rel="stylesheet">
<script src="{{ mix('js/app.js') }}"></script>
</head>
<body>
#inertia
</body>
</html>
web.php:
Route::inertia('/drafts', 'drafts');

I had the same problem.
Here is how your app.js file must look like:
https://inertiajs.com/client-side-setup
summarizing:
Remove: Vue.use(App)
Change: import(./pages/${name}).then((module) => module.default),
by require(./Pages/${name}).default,

Related

Laravel - Fresh VueJS and Inertia app giving error: Do not mount Vue to <html> or <body> - mount to normal elements instead

I have just done a fresh install of inertia on an app with vuejs (v2) and am getting this error:
[Vue warn]: Do not mount Vue to <html> or <body> - mount to normal elements instead.
But I don't see why it's trying to mount on those elements? As far as I can tell I've followed the inertia installation guide....
web.php
Route::get('test', function(){return \Inertia\Inertia::render('master');});
app-ihf.js
import { App, plugin } from '#inertiajs/inertia-vue'
import Vue from 'vue'
import { InertiaProgress } from '#inertiajs/progress'
Vue.use(plugin)
const el = document.getElementById('app')
new Vue({
render: h => h(App, {
props: {
initialPage: JSON.parse(el.dataset.page),
resolveComponent: name => require(`./Pages/${name}`).default,
},
}),
}).$mount(el)
InertiaProgress.init()
master.blade.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/css/app-ihf.css">
<script src="{{ mix('/js/app-ihf.js') }}"></script>
</head>
<body>
#inertia
</body>
</html>
Can anyone see what's going wrong here? This is the html when you visit that route
<html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/css/app-ihf.css?id=fc17ae1fae0b57440a59">
<script src="/js/app-ihf.js?id=fa7eba2a2c660c498a3e"></script>
</head>
<body>
<div id="app" data-page="{"component":"master","props":{"errors":{}},"url":"\/test","version":"3993c0d73e25e92aa0e15607a6c438ef"}"></div>
</body></html>
I had the exact same issue and it's because I didn't put defer into the script tag so the JavaScript in app.js was running before the id="app" element existed on the page.
So in your case you need:
<script src="{{ mix('/js/app-ihf.js') }}" defer></script>

Laravel 8 - Jetstream + inertia.js - Vue dev tools not working

I have a project using Laravel 8, inertia js, Vue.js and webpack.
The VueJs chrome dev tools aren't working for this project. It keeps showing as not detected, i've tried restarting it, removing and readding the dev tools. I've checked in both dev and production, no vuejs detected. Any help would be great.
App.js
require("./bootstrap");
// Import modules...
import { createApp, h } from "vue";
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);
wepack.mix.js
const mix = require("laravel-mix");
mix.js("resources/js/app.js", "public/js")
.vue()
.postCss("resources/css/app.css", "public/css", [
require("postcss-import"),
require("tailwindcss"),
require("autoprefixer"),
])
.webpackConfig(require("./webpack.config"));
if (mix.inProduction()) {
mix.version();
} else {
mix.sourceMaps(false, "source-map");
}
app.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght#400;600;700&display=swap">
<!-- Styles -->
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
<!-- Scripts -->
#routes
<script src="{{ mix('js/app.js') }}" defer></script>
</head>
<body class="font-sans antialiased">
#inertia
</body>
</html>
i had the same problem in chrome and opera gx, the solution for me was:
Install Vue.js devtools beta;
Close and Reopen your Browser.
In case anyone has the same issue, the chrome extenstion also needs the vuejs devtools dev version to work. But this encountered another issue. Vue not appearing in the dev/inspect tool. Removing a chrome theme and setting this to default brought this back.

Change laravel html lang variable

I have laravel/VueJs app which is supporting multiple language but there is one issue, when I change language on VueJs html Lang tag will not change.
Code
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="csrf-token" content="{{ csrf_token() }}" />
<title>{{ config('app.name', 'Laravel') }}</title>
<link href="{{ asset('css/app.css') }}" rel="stylesheet" />
<style>body{ margin-bottom: 60px !important;}</style>
</head>
<body style="overflow:hidden;">
<noscript>
<strong>We're sorry but Xtreme Vuesax doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<script src="{{ asset('js/app.js') }}"></script>
<script>
window.default_locale = "{{ config('app.locale') }}";
window.fallback_locale = "{{ config('app.fallback_locale') }}";
</script>
</body>
</html>
app.js
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
import localesData from './components/Layouts/localesData'
Vue.component('locale-dropdown', require('./components/Layouts/locales').default);
const i18n = new VueI18n({
locale: 'en',
messages: localesData,
})
const app = new Vue({
el: '#app',
router,
store,
i18n,
render: h => h(App)
});
Explanation
I need this line <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> to be change to selected language in VueJs.
any idea how to change that?
From within your Vue component 'locale-dropdown', when the user selects a locale, you can
//say the data property on your component which holds the selected locale is called locale
let h = document.querySelector('html');
h.setAttribute('lang', this.locale);

How to setup inertia on my project, gives me an error when I try and load the login page

I'm trying to setup Inertia to use in my Laravel project but it gives me errors? Where is my mistake?
I installed Inertia with this command
composer require inertiajs/inertia-laravel
followed the instructions on the github page and added #inertia to my app.blade.php like this:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
<link rel="icon" type="image/jpg" href="{{asset("/image/logo2.png")}}">
<!-- Fonts -->
<link rel="dns-prefetch" href="//fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
#inertia
</body>
</html>
in my Login Controller
public function showLoginForm()
{
return Inertia::render('Auth/Login');
}
in my routes/web.php
Auth::routes();
Route::get('login', 'Auth\LoginController#showLoginForm')->name('login');
Route::post('login', 'Auth\LoginController#login');
This is the error I get:
the lines that is highlighted is the #inertia which show up as this
<div id="app" data-page="<?php echo e(json_encode($page)); ?>"></div>
What am i doing wrong?
#inertia blade directive is working but not rendered because you need to install the frontend adapter
npm install #inertiajs/inertia #inertiajs/inertia-vue
Set it up in webpack.mix.jsĀ 
const mix = require('laravel-mix')
const path = require('path')
mix.js('resources/js/app.js', 'public/js')
.webpackConfig({
output: { chunkFilename: 'js/[name].js?id=[chunkhash]' },
resolve: {
alias: {
vue$: 'vue/dist/vue.runtime.esm.js',
'#': path.resolve('resources/js'),
},
},
})
And initialize it in Vue resources/js/app.js
import { InertiaApp } from '#inertiajs/inertia-vue'
import Vue from 'vue'
Vue.use(InertiaApp)
const app = document.getElementById('app')
const pages = {
'Auth/Login': require('./Pages/Auth/Login.vue').default,
}
new Vue({
render: h => h(InertiaApp, {
props: {
initialPage: JSON.parse(app.dataset.page),
resolveComponent: name => pages[name],
},
}),
}).$mount(app)

How to set vue component when root of site is opened

In my laravel 5.6/vue.js 2.5.7 / vuetify": "^1.0.8" I need to set vue component when root of site is opened
I mean when I run url
http://local-artists-rating.com
see url reopened
http://local-artists-rating.com/#/
It has navbar, footer defined in my pages, but not any content I defined in resources/assets/js/components/appRoot.vue.
In my resources/assets/js/app.js:
require('./bootstrap');
window.Vue = require('vue');
import Vue from 'vue'
import VueRouter from 'vue-router';
window.Vue.use(VueRouter);
...
import AppRoot from './components/appRoot.vue';
...
const routes = [
{
path: '/',
components: {
...
appRoot: AppRoot,
...
}
...
{path: '/not-found/:invalid_url?', component: NotFound, name: 'notFound'},
{path: '/login', component: AppLogin, name: 'appLogin'},
{path: '/', component: AppRoot, name: 'appRoot'},
}
...
const router = new VueRouter( {
mode: 'hash', // default
routes
})
router.beforeEach((to, from, next) => {
if (!to.matched.length) {
next( '/not-found/'+encodeURIComponent(to.path) );
} else {
next();
}
})
...
new Vue({ router, i18n,
data:{
app_title: '',
},
mixins : [appMixin],
created() {
}, // created() {
mounted() {
}, // mounted(){
} ).$mount('#app') // new Vue({ router,
If I commented line :
path: '/',
at top of routes definitions, I got error in console:
app.js?dt=1529909735:73635 Uncaught Error: [vue-router] "path" is required in a route configuration.
at assert (app.js?dt=1529909735:73635)
at addRouteRecord (app.js?dt=1529909735:74771)
at app.js?dt=1529909735:74741
at Array.forEach (<anonymous>)
at createRouteMap (app.js?dt=1529909735:74740)
at createMatcher (app.js?dt=1529909735:74961)
at new VueRouter (app.js?dt=1529909735:76055)
at Object._typeof (app.js?dt=1529909735:4945)
at __webpack_require__ (app.js?dt=1529909735:20)
at Object.<anonymous> (app.js?dt=1529909735:50854)
In my resources/views/layouts/app.blade.php:
<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
<head>
<?php $current_template= 'artists_rating_light' ?>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Cache-Control" content="no-cache">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title id="app_title">{{ config('app.name', 'Laravel') }}</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.css">
<link href="https://use.fontawesome.com/releases/v5.0.8/css/all.css" rel="stylesheet">
</head>
<body>
<div id="app">
<backend-app-layout></backend-app-layout>
</div>
#include('layouts.footer')
<script src="{{ asset('js/app.js' ) }}{{ "?dt=".time() }}"></script>
</body>
</html>
Which is the right way ?
Thanks!

Resources