Using Laravel Inertia.js, Vue and Blade in parallel? - laravel

Is there a way to use Laravel Blade for one part of a multipage site (e-commerce), and Inertia/Vue for some specific pages (like the basket and the admin pages)? Not mixing the two on the same pages, as I see it done with other commentaries.
The first category is a load of pages that are merely static, need fast loading and robust SEO referencing (product pages and catalogues). The second do not need to be indexed, but need a lot of user interactions.
I have tried a few things with my first project, but I don’t seem to be able to call Laravel routes when Inertia is active. Plus it would not really make sense to load all Inertia and Vue in the Blade pages. So as a starter I guess I would need to load the Inertia + Vue code only on the Vue pages (admin and basket). And I guess there are a lot of other issues to take care of.
Or maybe scrap Inertia.js, and just load vanilla Vue.js on the Vue pages? But then that means loading the router and the datastore as well...
Many thanks for any idea on the best way to proceed!
E.

You can mix pages as you want:
1. For Inertia pages.
// View:
<inertia-link href="/dashboard">dashboard</inertia-link>
// Laravel controller:
public function index(Request $request)
{
return Inertia::render('Dashboard/Index', [
'data' => [
// ...
],
]);
}
2. Blade pages.
// View:
dashboard
// Laravel controller:
public function index(Request $request)
{
return view('dashboard.index', [
'data' => [
// ...
],
]);
}

Related

How to disable personal teams in Laravel / Jetstream when using Inertia?

I followed an article here:
https://devlan.io/disabling-personal-teams-in-laravel-8-and-jetstream-1fd083593e08
Basically to disable personal teams in Laravel / Jetstream. Now the article gives the example of how to achieve this using Livewire but I am using Inertia. The Livewire template needs this to be changed from this:
#if (Laravel\Jetstream\Jetstream::hasTeamFeatures()
To this:
#if (Laravel\Jetstream\Jetstream::hasTeamFeatures() && Auth::user()->isMemberOfATeam())
How would I achieve this in Inertia? I have had a look around the web, but because I am new to this stack I am completely stumped.
Thanks in advance.
This is a conditional made in Blade templates. Since Inertia doesn't work with Blade, instead it uses some JavaScript framework (Vue, React, Svelte), what you need to do is to run this conditional somewhere in the Laravel side (Controller, Middleware) and set a variable that you'll pass your client side component to conditionally render the teams html stuff.
If you want to have this flag available to all the pages in your app, you can do this through the HadleInertiaRequests middleware.
class HandleInertiaRequests extends Middleware
{
public function share(Request $request)
{
return array_merge(parent::share($request), [
'has_teams' => Laravel\Jetstream\Jetstream::hasTeamFeatures() && Auth::user()->isMemberOfATeam()
]);
}
}
Then, your component, you can use that variable to render the teams part or not (Example using Vue):
<div v-if="$page.props.has_teams">
<!-- Teams... -->
</div>

how to navigate between components in Laravel using dynamic component

I'm working on a little project using Laravel and VueJs, I'm also using dynamic component in my blade template.
I would like to know home can I navigate between pages(components) since I'm not using vue-router.
this is my code :
methods: {
register(url){
Csrf.getCookie().then(() => {
User.register(url, this.form)
.then(() => {
// how can i redirect the user since i'm not using vue router / should i use vue router ?
})
.catch(error => {
});
})
}
}
Your choices are pretty much either:
Use vue-router, including its element on a single Blade view and then navigating between Vue routes with <router-link> or this.$router.push()
Use a single Vue component per Blade view in Laravel, navigating between them with a standard <a href> link

Laravel Jetstream Adding Google Analytics

I am struggling to get Google Analytics to report correctly using the InertiaJS stack of Laravel Jetstream. I need to track individual page visits but since it's a SPA I'm unsure how to go about this. I have placed the tag in my app.blade but that shows me all traffic, not specific to each page, nor can I trigger events.
What's the best way to go about getting GA onto a Laravel Jetstream Inertia stack?
I opted in for using Inertia::share then on my app.blade I referenced the respective elements such as title etc as props.
Eg. RouteController (returns Inertia View):
Inertia::share([
'title' => $title,
'description' => $description,
'meta_image' => $meta_image,
'meta_url' => $meta_url
]);
return Inertia::render...
App.blade:
<title>{{$page['props']['title'] ?? ''}}</title>
<meta name="description" content="{{$page['props']['description'] ?? ''}}">
...
And finally in my AppLayout.vue I have a watch on these props for page changes:
watch: {
"$page.props.title"(newTitle) {
this.setPageData();
},
"$page.props.description"(newDescription) {
this.setPageData();
},
},
Only really need to watch the Title as robots should load each page fresh (for SEO purposes) but the this works well for meta tags (Open Graph) and also GA to track each page.

Laravel 8x create user table with JetStream Teams

I am building a web app and running Laravel teams, I have made a user table but am unsure how to nest the data so that the users are viewing their main team. From my research I have found:
return App\Models\Calendar::where(
'team_id', $request->user()->currentTeam->id
)->get();
or
// Access a user's "personal" team...
$user->personalTeam() : Laravel\Jetstream\Team
but I need a little help applying it properly as I've never done it.
My current view, Controller, and route are:
View is just a standard table which I built to show with a foreach method:
<div class="">
{{$user->name}}
</div>
Controller:
public function render()
{
# Load all users and sort by name
return view('users.table',[
'users' => User::orderBy('name')->paginate($this->perPage)
]);
}
Route:
Route::middleware(['auth:sanctum', 'verified'])->group( function () {
Route::resource('users', \App\Http\Livewire\Users::class);
});
I tried to cut down the code so it's easier to give me suggestions, let me know if I missed anything.
This is my current screenshot of the users table:
File tree
Change
User::orderBy('name')->paginate($this->perPage)
with
Team::find(Auth::user()->current_team_id)->users()->paginate($this->perPage)

Laravel routes with vue/vue router

I'm basically using VueRouter to create all my routes which is working really well. However, my application is built using Laravel. So if I refresh any of the routes I get an error that the route is not defined. So at the minute in every controller I've had to add an index function. This just returns the view of my app.blade which is just the usual tags etc and the to load my single page app. I'm just wondering if there is a cleaner solution? I guess I could move the return view into a single Controller and make my Controllers extend this. But I'm just wondering if there is a better way I'm missing?
i.e. one of my routes via VueRouter:
{
path: "/clients",
name: "clients",
component: () => import(/* webpackChunkName: "clients" */ "../resources/js/components/Views/Clients/Clients.vue")
},
The route in my clients.php file
Route::get('/clients', [App\Http\Controllers\ClientController::class, 'index'])->name('clients');
Then the ClientController index function
public function index()
{
return view('app');
}
It would just be nice to have the loading of the app.blade done somewhere else and not need to be specified per controller. Any help would be appreciated to ensure it's all done efficiently!
Thanks!
Here is how I solved this issue for one of my projects which is also single page application in Vue and Laravel: https://github.com/lyyka/laravel-vue-blog-spa/blob/master/routes/web.php
Simply, in your routes file, you put this code:
Route::get('/{any}', function () {
return view('welcome');
})->where("any", ".*");
And in my welcome view I have:
#extends('layouts.app')
#section('content')
<div class = "container">
<router-view></router-view>
</div>
#endsection
Basically this will return your app view for any URL and so your Vue SPA should work properly. Generally, it is not a good practice to put callback functions inside your routes file, but in this case, you won't even be using your routes file as it is a SPA, so this solution can pass! :)
You should use your single html file and make a controller.
On your controller
public function index(){
return view('index');
}
on your web.php
basically, you should make the same route on your laravel and vue
Route::get('/products', [ProductsController::class,'index']);
in my vue-routes
import Products from './components/Products.vue'
{
path:'/products'
component: Products
}

Resources