Creating a layout file in Laravel, Vue, Inertia Js - laravel

I'm new to Vue and Inertia Js, so far I understand that in Inertia, u can call Vue components with layouts, like navbar and sidebar etc.
but what I'm trying to achieve is to create a layout of the whole app, that consists of multiple vue files for example like this,
<template>
<NavbarVue/>
<Home/>
<Kenapa/>
<Cerita/>
<Karir/>
<Lowongan/>
<Media/>
<Gabung/>
<Mitra/>
<Download/>
<Footer/>
</template>
<script setup lang="ts">
import NavbarVue from '../components/Navbar.vue';
import Home from '../pages/Home.vue';
import Media from '../pages/Media.vue';
import Kenapa from '../pages/Kenapa.vue';
import Cerita from '../pages/Cerita.vue';
import Lowongan from '../pages/Lowongan.vue';
import Karir from '../pages/Karir.vue';
import Gabung from '../pages/Gabung.vue';
import Mitra from '../pages/Mitra.vue';
import Download from '../pages/Download.vue';
import Footer from '../components/Footer.vue';
</script>
In vue.js, I can create a layout for the app like that, by creating a template for different vue files like Home page, Kenapa page etc.
But in Inertia Js, this is the app.js file
import './bootstrap';
import '../css/app.css';
import { createApp, h } from 'vue';
import { createInertiaApp } from '#inertiajs/vue3';
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);
},
progress: {
color: '#4B5563',
},
});
What should I do to achieve that ?

You must use a persistent layout for that.
Layout.vue
<template>
<div>
<Navbar />
<slot /> <!-- Don't forget this -->
<Footer />
</div>
</template>
<script setup lang="ts">
import Navbar from '../components/Navbar.vue';
import Footer from '../components/Footer.vue';
</script>
MyPage.vue
<script>
import Layout from './Layout'
export default {
layout: Layout,
}
</script>
<script setup>
defineProps({ user: Object })
</script>
<template>
<H1>My Page</H1>
<p>Hello {{ user.name }}, welcome to my page!</p>
</template>

Related

Default route is not working with laravel and vue

I am creating a single page application using laravel and vue. it's not loading index component on page load.
web.php
Route::get('{any}', function () {
return view('welcome');
})->where('any', '.*');
Welcome.blade.php
<body>
<div id="app">
<router-view></router-view>
</div>
<script src="{{asset('js/app.js')}}"></script>
</body>
router.js file
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter)
const routes = [
{ path: '/', component: require('./components/IndexComponent.vue') },
{ path: '/login', component: require('./components/LoginComponent.vue') }
]
const router = new VueRouter({
routes:routes,
mode:'history'
})
export default new VueRouter({router})
app.js file
require('./bootstrap');
window.Vue = require('vue');
import vuetify from './vuetify';
import router from './router';
import Index from './components/IndexComponent';
import Login from './components/LoginComponent';
var app = new Vue({
el: '#app',
router,
vuetify,
components: {
'index-component':Index,
'login-component':Login
}
});
Index Component (IndexComponent.vue)
<template>
<router-link to="/" class="nav-item nav-link">Home</router-link>
<router-link to="/login" class="nav-item nav-link">Login</router-link>
<router-view></router-view>
</template>
I had the same problem. Open your project in chrome and press Ctrl + Shift + I (Open console). Now after the login you can see that there is a warning which says: No match for favicon.ico. To solve this problem you go to your routes file and define a redirect:
{
path: '/favicon.ico',
redirect: '/user/dashboard'
}

How to install Vuetify in Laravel 8 with jetstream-inertia?

I'm trying to install Vuetify on the latest Laravel versione (8) but I cannot do it. Seems it doesn't work even if the console doesn't show me any error.
That's my resource/plugins/vuetify.js
import Vue from 'vue'
// import Vuetify from 'vuetify'
import Vuetify from 'vuetify/lib'
// import 'vuetify/dist/vuetify.min.css'
Vue.use(Vuetify)
const opts = {}
export default new Vuetify(opts)
My webpack.mix.js :
const mix = require('laravel-mix')
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin')
mix
.js('resources/js/app.js', 'public/js')
.postCss('resources/css/app.css', 'public/css', [
require('postcss-import'),
require('tailwindcss'),
])
.webpackConfig({
plugins: [
new VuetifyLoaderPlugin()
],
})
.browserSync('tb8.test');
The app.js
import PortalVue from 'portal-vue';
Vue.use(InertiaApp);
Vue.use(InertiaForm);
Vue.use(PortalVue);
Vue.use(vuetify);
const app = document.getElementById('app');
new Vue({
vuetify,
render: (h) =>
h(InertiaApp, {
props: {
initialPage: JSON.parse(app.dataset.page),
resolveComponent: (name) => require(`./Pages/${name}`).default,
},
}),
}).$mount(app);
and the welcome.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">
<title>Laravel</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght#400;600;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Nunito';
}
</style>
</head>
<body class="antialiased">
<div class="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center sm:pt-0">
#if (Route::has('login'))
<div class="hidden fixed top-0 right-0 px-6 py-4 sm:block">
#auth
Dashboard
#else
Login
#if (Route::has('register'))
Register
#endif
#endif
</div>
#endif
<v-app>
<v-main>
Hello World
</v-main>
</v-app>
</div>
</body>
</html>
Can anyone help me to find where is the mistake?
Thank you in advance
Valerio
Fresh Laravel 8.12 + Jetstream + Inertia + VueJs + Vuetify
add to header the string of style in /resources/views/app.blade.php
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
add to /resources/js/app.js
import Vuetify from 'vuetify';
import 'vuetify/dist/vuetify.min.css';
Vue.use(Vuetify)
and
vuetify: new Vuetify(), after 'new Vue({' like this:
require('./bootstrap');
import Vue from 'vue';
import Vuetify from 'vuetify';
import { InertiaApp } from '#inertiajs/inertia-vue';
import { InertiaForm } from 'laravel-jetstream';
import PortalVue from 'portal-vue';
import 'vuetify/dist/vuetify.min.css';
Vue.mixin({ methods: { route } });
Vue.use(InertiaApp);
Vue.use(InertiaForm);
Vue.use(PortalVue);
Vue.use(Vuetify)
const app = document.getElementById('app');
new Vue({
vuetify: new Vuetify(),
render: (h) =>
h(InertiaApp, {
props: {
initialPage: JSON.parse(app.dataset.page),
resolveComponent: (name) => require(`./Pages/${name}`).default,
},
}),
}).$mount(app);
After that, for example, you can create your vuetify component like this:
/resources/js/Components/NavigationDrawers.vue with code from Vuetify labrory
init this vue-component in /resources/js/Pages/Dashboard.vue like
<navigation-drawers/>
with call
import NavigationDrawers from '#/Components/NavigationDrawers'
and
NavigationDrawers
in <script>
Example:
<template>
<app-layout>
<navigation-drawers/>
....
....
</app-layout>
</template>
<script>
import NavigationDrawers from '#/Components/NavigationDrawers'
import AppLayout from '#/Layouts/AppLayout'
import Welcome from '#/Jetstream/Welcome'
export default {
components: {
AppLayout,
Welcome,
NavigationDrawers,
},
}
</script>
It is help you for setting vuetify to your project.
Sass and other config you can config self.
a screenshot example Navigation Drawer
a screenshot example Navigation Drawer two
Currently Vuetify does not work with vue 3, so to install vuetify you have to go with vue 2. to do so:
we can install jetstream 2.1 which comes with vue 2. I have described installation process below:
Youtube video: https://youtu.be/V8_yLfNhg2I
To install laravel
composer create-project laravel/laravel project_name
Now go to composer.json file and inside require:{} add just one line and rest of composer file should be same.
"laravel/jetstream": "2.1",
after adding that "require" section of composer.json would look something like this:
"require": {
"php": "^7.3|^8.0",
"fideloper/proxy": "^4.4",
"fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^7.0.1",
"laravel/framework": "^8.40",
"laravel/tinker": "^2.5",
"laravel/jetstream": "2.1",
},
Now run composer update
Now run php artisan jetstream:install inertia
Now run npm install
Now run npm install vuetify
Go to resources/css/app.css and add following
#import url('https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900');
#import url('https://cdn.jsdelivr.net/npm/#mdi/font#5.x/css/materialdesignicons.min.css');
#import "vuetify/dist/vuetify.min.css";
Now go to resources/js/app.js and add following code:
require('./bootstrap');
// Import modules...
import Vue from 'vue';
import { App as InertiaApp, plugin as InertiaPlugin } from '#inertiajs/inertia-vue';
import PortalVue from 'portal-vue';
//add these two line
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
Vue.mixin({ methods: { route } });
Vue.use(InertiaPlugin);
Vue.use(PortalVue);
//also add this line
Vue.use(Vuetify);
const app = document.getElementById('app');
new Vue({
//finally add this line
vuetify: new Vuetify(),
render: (h) =>
h(InertiaApp, {
props: {
initialPage: JSON.parse(app.dataset.page),
resolveComponent: (name) => require(`./Pages/${name}`).default,
},
}),
}).$mount(app);
Now run npm run dev
At this moment your vuetify will work!
To check whether vuetify with inertia js is working or not please follow:
Go to resources/js/Pages and create new file name test.vue
Add following code to test.vue
<template>
<v-app>
<v-container>
<v-btn>Click Me!</v-btn>
</v-container>
</v-app>
</template>
Now run npm run dev
Now go to route/web.php and add
Route::get('/', function () {
return Inertia::render('test');
});
Now php artisan serve to run in browser. and don't forget to add migrate and add database to .env
Vuetify now has a Vue 3 branch (at the time of writing still in beta) The point about the clash with tailwind still stands although the problem is mostly manifests its self in terms of file size (of the css) Anyway to get things working in an install of Laravel (9) and Jetstream with Inertia you need to add vuetify
npm install vuetify#^3.0.7 --save
Then edit resources/js/app.js
by adding:
// Vuetify
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
const vuetify = createVuetify({
components,
directives,
})
and in the same file amending the createInertiaApp function set up so that Vue uses Vuetify
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(vuetify)
...
},
});
You will then be able to use Vuetify components. You will probably want to set your own colours. There are two options SASS or javascript
here is an example of the Javascript option
const vuetify = createVuetify({
theme: {
themes: {
light: {
dark: false,
colors: {
primary: "#415e96",
secondary: "#b89acc"
}
},
},
},
components,
directives,
}
)
More on this here
Here is an (untested by me) article on removing the collisions between tailwind and Vuetify

Vuejs component disappears on page load

I'm experiencing a weird issue in vue. I've set up a component to view details of an item, this component accepts props and renders on first load but when i reload the page, the entire component disappears including the Root.
I've tried to name router-view but it doesn't work.
MainApp.vue
<template>
<div class="container">
<div>
<transition name="fade">
<router-view></router-view>
</transition>
</div>
</div>
</template>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s
}
.fade-enter, .fade-leave-active {
opacity: 0
}
</style>
<script>
export default{
}
</script>
Routes.js
import ViewProduct from './store/View.vue'
const routes = [
{
name: 'viewProduct',
path: 'product/:id/view/:slug',
component: ViewProduct,
props: true
}
];
export default routes;
Main.js
import VueRouter from 'vue-router';
Vue.use(VueRouter);
import routes from './routes';
const router = new VueRouter({ mode: 'history', routes});
import MainApp from './MainApp'
import store from './store/store/index'
new Vue({
el: '#storeapp',
render: h => h(MainApp),
router,
store: store,
});
I have another router-view container which works fine but this one does not.

Child routes are still only loading parent component

So I'm trying to create a a settings page that has child routes. For example, I want to have /settings/user, then /settings/branches, etc. However, everytime I load /settings or any of its child routes it only shows the parent Settings component.
Here is my routes.js file
// Imports
import Vue from 'vue';
import VueRouter from 'vue-router';
import Store from './store';
// Set to use
Vue.use(VueRouter);
// Views
import Home from './views/Home/';
import UserIndex from './views/UserIndex';
// Grab Routes
import Settings from './routes/Settings'
// Create our routes
const routes = [
{
path: '/',
name: 'home',
component: Home,
},
{
path: '/users',
name: 'users.index',
component: UserIndex,
},
].concat(Settings);
Here is my Settings.js (which is later contacted in my main routes folder)
// Routes for /Settings/
import Settings from '../views/Settings/';
import Branches from '../views/Settings/Branches';
const routes = [
{
path: '/settings',
name: 'settings',
component: Settings,
children: [
{
name: 'branches',
path:'branches',
component: Branches
}
]
}
]
export default routes;
/views/settings/Branches.vue
<template>
<div>
<p>Branches page</p>
</div>
</template>
<script>
export default {
components: {
}
}
</script>
/views/settings/index.vue
<template>
<div>
<p>settings page</p>
</div>
</template>
<script>
export default {
components: {
}
}
</script>
Just include <router-view></router-view> to settings page, so it can render its own children. Then you can navigate to it through /settings/branches link.
Reference
<template>
<div>
<p>Settings page</p>
<router-view></router-view>
</div>
</template>

How correctly include VueRouter in Laravel Project?

I try to implement VueRouter in Laravel project but arreas error Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
app.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './components/App'
import ExampleComponent from './components/ExampleComponent'
import ExampleComponent1 from './components/ExampleComponent1'
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
{
path: '/',
component: ExampleComponent
},
{
path: '/example',
component: ExampleComponent1
}
]
})
const app = new Vue({
el: '#app',
router,
template: `<app></app>`,
components: {
App
}
})
components/App.vue
<template>
<div>
<div>
<router-link :to="'/'"></router-link>
<router-link :to="'/example'"></router-link>
</div>
<div>
<router-vue></router-vue>
</div>
</div>
</template>
<script>
export default {
}
</script>
how can I connect correctly vue-router?
I see that you've misspelled <router-view /> in App.vue which is probably causing the warning.

Resources