skip to Main Content

So I am working on a Laravel 8 app, with Inertia and Vue.

The idea is that most of the pages are Laravel + Blade (good for SEO, fast loading etc…), but for selected pages that need a lot of user interactions, I insert a Vue component in the Blade Template where the interactions need to happen.

With Inertia, this is done by calling the Vue component with return Inertia::render('vueComponent') in the Controller that is called by the Laravel Route. Data can be passed to the Vue instance, and even to the Blade template, so this is good (see below).

namespace AppHttpControllers;
use InertiaInertia;

class RangePageController extends Controller
{
    public function show(string $lang='fr')
    {
        // Strip the trailing slash from $lang
        $lang = Str::before($lang, '/');

        return Inertia::render('ProductsGallery', ['bar' => "Hello World"])->withViewData(['lang' => $lang]);
    }
}

And by default, the file "/resources/views/app.blade.php" is rendered with the Vue component replacing the @inertia directive (plus some Vue Data). Neat.

By default, the Blade layout file "app.blade.php" is used. The doc specifies that the default can be changed: InertiaInertia::setRootView('name');.

The Question: rather than changing the default, is there a way to choose different Blade layout files when calling different pages from the Controller (and inject the Vue component as above)? For instance I would like to use one Blade layout for my e-commerce basket, and a different one for my admin pages. Like choosing "app1.blade.php" for a page, and "app2.blade.php" for another.

Many thanks!
E.

3

Answers


  1. Chosen as BEST ANSWER

    Found a solution, for what it is worth.

    1. I created 2 new AppHttpMiddleware, extending the HandleInertiaRequest.php middleware.
    2. In each extended class, I set the protected $rootView to point to the custom Blade layout file in /resources/views.
      For instance protected $rootView = 'admin.app';, to point to /resources/views/admin/app.blade.php, and the same for the 'web' app.blade.php.
    3. Then I created a second "admin" middleware group in Kernel.php replicating the list in the "web" group, and I replace the default AppHttpMiddlewareHandleInertiaWebRequests::class lines with the extended classes (in the "web" and the "admin" groups).
    4. And I created an "admin" route file in the "routes" folder to host the routes that will use the "admin" layout. The routes in the default "web" route file will use the Blade layout that sits in resources/views/web/.

    Probably some better solutions, but this one seems to work.

    Note: I have seen a discussion on GitHub to do the same, but in addition to have 2 different Vue instances: one for "web", and one for "admin". Not sure what this brings, but I am still looking for a way to do it! If anybody has an idea...


  2. You can change the root template of interia in middleware(HandleInertiaRequest.php) using property and also with method

    // Set root template via property
    protected $rootView = 'app';
    
    // OR
    // Set root template via method
    public function rootView(Request $request)
    {
        return 'app';
    }
    

    Now filter the request in rootView() method and change the root template according to your need just using a simple if-else conditions.

    Login or Signup to reply.
  3. Just a little bit update your HandleInertiaRequests

    public function version(Request $request)
        {
            // Add the root view tho the version hash.
            // This forces inertia to make a hard reload when the template changes.
            return $this->rootView . parent::version($request);
        }
    
    public function handle(Request $request, Closure $next, $rootView = null)
        {
            if ($rootView) {
                $this->rootView = $rootView;
            }
    
            return parent::handle($request, $next);
        }
    

    Also remove HandleInertiaRequests from global middleware and add it as named middleware

        protected $routeMiddleware = [
             ...
            'inertia' => AppHttpMiddlewareHandleInertiaRequests::class,
        ];
    

    and now you can populate routes, routes groups as you need

    Route::group(['middleware' => ['Admin:Client.Dashboard.app']], function () {
        Route::get('/admin/dashboard', [
            'as'   => 'admin.dashboard',
            'uses' => 'AdminDashboardController@index',
        ]);
    });
    Route::middleware('inertia:app')
        ->group(base_path('routes/auth.php'));
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search