Last active
July 27, 2024 08:17
-
-
Save reinink/65f85856d4f4674be95f1579989e6b84 to your computer and use it in GitHub Desktop.
Multi-page Vue App in Laravel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>{{ isset($title) ? $title.' - '.Config::get('app.name') : Config::get('app.name') }}</title> | |
<link href="{{ mix('/css/app.css') }}" rel="stylesheet"> | |
<script src="{{ mix('/js/manifest.js') }}" defer></script> | |
<script src="{{ mix('/js/vendor.js') }}" defer></script> | |
<script src="{{ mix('/js/app.js') }}" defer></script> | |
@routes | |
</head> | |
<body> | |
<div id="app" | |
data-vue-component="{{ $name }}" | |
data-vue-props="{{ json_encode($data) }}" | |
data-csrf-token="{{ csrf_token() }}" | |
data-auth="{{ json_encode(['user' => Auth::user() ? Auth::user()->only('id', 'first_name', 'last_name') : null]) }}" | |
></div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Vue from 'vue' | |
import axios from 'axios' | |
const root = document.getElementById('app') | |
Vue.prototype.$http = axios | |
Vue.prototype.$http.defaults.headers.common['X-CSRF-TOKEN'] = root.dataset.csrfToken | |
Vue.prototype.$http.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest' | |
Vue.prototype.$route = route | |
const files = require.context('./', true, /\.vue$/i) | |
files.keys().map(key => Vue.component(key.split('/').slice(-1)[0].split('.')[0], files(key))) | |
new Vue({ | |
render: h => h(Vue.component(root.dataset.vueComponent), { props: JSON.parse(root.dataset.vueProps) }) | |
}).$mount(root) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Providers; | |
use Illuminate\Support\Facades\View; | |
use Illuminate\Support\ServiceProvider; | |
use Illuminate\View\Factory as ViewFactory; | |
class AppServiceProvider extends ServiceProvider | |
{ | |
/** | |
* Bootstrap any application services. | |
*/ | |
public function boot() | |
{ | |
ViewFactory::macro('component', function ($name, $viewData = [], $componentData = []) { | |
return View::make('app', ['name' => $name, 'data' => $componentData] + $viewData); | |
}); | |
} | |
/** | |
* Register any application services. | |
*/ | |
public function register() | |
{ | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<layout> | |
<h1>Create User</h1> | |
<form @submit.prevent="submit"> | |
<text-input label="First name" v-model="form.first_name" :error="errors.get('first_name')"></text-input> | |
<text-input label="Last name" v-model="form.last_name" :error="errors.get('last_name')"></text-input> | |
<text-input label="Email" v-model="form.email" :error="errors.get('email')"></text-input> | |
<text-input label="Password" v-model="form.password" :error="errors.get('password')" type="password" autocomplete="new-password"></text-input> | |
<button type="submit" :disabled="sending">Create User</button> | |
</form> | |
</layout> | |
</template> | |
<script> | |
export default { | |
data() { | |
return { | |
form: { | |
first_name: null, | |
last_name: null, | |
email: null, | |
password: null, | |
}, | |
sending: false, | |
errors: ErrorBag.new({}), | |
} | |
}, | |
methods: { | |
submit() { | |
this.sending = true | |
axios.post(route('users.store'), this.form) | |
.then(response => window.location.href = route('users')) | |
.catch(error => { | |
this.sending = false | |
this.errors = ErrorBag.new(error.response.data.errors) | |
}) | |
}, | |
} | |
} | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div> | |
<header> | |
<img src="logo.png"> | |
</header> | |
<nav> | |
<a :href="route('users')" :class="route().current('users*') ? 'active' : 'not-active'">Users</a> | |
<a :href="route('companies')" :class="route().current('companies*') ? 'active' : 'not-active'">Companies</a> | |
<a :href="route('products')" :class="route().current('products*') ? 'active' : 'not-active'">Products</a> | |
<a :href="route('settings')" :class="route().current('settings*') ? 'active' : 'not-active'">Settings</a> | |
</nav> | |
<main> | |
<slot></slot> | |
</main> | |
</div> | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Controllers; | |
use App\User; | |
use Illuminate\Support\Facades\View; | |
use Illuminate\Support\Facades\Request; | |
class UsersController extends Controller | |
{ | |
public function index() | |
{ | |
return View::component('Users', ['title' => 'Users'], [ | |
'search' => Request::get('search'), | |
'users' => User::orderByName() | |
->search(Request::get('search')) | |
->paginate(15, ['id', 'first_name', 'last_name', 'email']) | |
->appends(Request::all()), | |
]); | |
} | |
public function create() | |
{ | |
return View::component('CreateUser', ['title' => 'Create User']); | |
} | |
public function store() | |
{ | |
$input = Request::validate([ | |
'first_name' => ['required', 'max:50'], | |
'last_name' => ['required', 'max:50'], | |
'email' => ['required', 'max:50', 'email'], | |
'password' => ['nullable'], | |
]); | |
User::create($input); | |
} | |
public function edit(User $user) | |
{ | |
return View::component('EditUser', ['title' => $user->name], [ | |
'user' => $user->only('id', 'first_name', 'last_name', 'email'), | |
]); | |
} | |
public function update(User $user) | |
{ | |
Request::validate([ | |
'first_name' => ['required', 'max:50'], | |
'last_name' => ['required', 'max:50'], | |
'email' => ['required', 'max:50', 'email'], | |
'password' => ['nullable'], | |
]); | |
$user->update(Request::only(['first_name', 'last_name', 'email'])); | |
if (Request::get('password')) { | |
$user->update(['password' => Request::get('password')]); | |
} | |
} | |
public function destroy(User $user) | |
{ | |
$user->delete(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let mix = require('laravel-mix') | |
mix.js('resources/js/app.js', 'public/js') | |
.extract(['vue', 'lodash', 'axios']) | |
.webpackConfig({ | |
resolve: { | |
alias: { 'vue$': 'vue/dist/vue.runtime.js' } | |
} | |
}) |
@JulianGarzon22 You might want to check out https://inertiajs.com. That's the progression of this idea. 👍
Is there any way to do this in Vue 3 + Vite?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is brilliant, I think I am going to use this stack again, thanks