1

I have an application with multiple web pages. On each webpage, I want to be able to bind a Vue instance to some element on the page as to give it a more dynamic user interaction.

In the base Laravel project, you're supposed to bind a Vue instance to #app in app.js which I've done. Including any more instances, however, give a "element not found" error when you're on any page that doesn't include that element. I imagine you're not supposed to put all of your instances in app.js...

What is the general architecture for having a different Vue instance on each page? Do I make a new js file for each page, and include it?

Sorry for my naivety!

2
  • Yes you should have VueJS instances declared in other files or as script tags in the blade view files of specific pages Commented Nov 2, 2019 at 19:20
  • Although I personally wouldn't care about that Vue warning, but an extra useless JS is also a good reason not to include it everywhere Commented Nov 2, 2019 at 19:20

2 Answers 2

2

You can create a new Vue instance on a yielded scripts section in app.blade.php that every view extends (mostly) for each page where needed to avoid the Vue warning

For example, Laravel Vapor website does* this, in the main page you can find this code

*they use a CDN to include the library instead of the compiled one from webpack

A Vue instance just for the Form

<script>
    var app = new Vue({
                el: '#form',
                data: {
                    email: '',
                    submitted: false,
                    submitting: false
                },
                methods: {
                    onSubmit: function () {
                        this.submitting = true;

                        fetch('/api/early-access', {
                            method: 'POST',
                            body: JSON.stringify({ email: this.email }),
                            headers: {
                                'Content-Type': 'application/json'
                            }
                        }).then(response => {
                            this.submitted = true;
                            this.submitting = false;
                        });
                    }
                }
            })
</script>

In layouts/app.blade.php yield a section for the scripts right before the closing tag of the body, for example

<main class="py-4">
            @yield('content')
        </main>
    </div>
    @yield('scripts')
</body>

Then instantiate a new Vue instance in the Blade view file of a page like so

@extends('layouts.app')

@section('content')
<div class="container">
    <div id="home-page"></div>
</div>
@endsection

@section('scripts')
<script>
    new Vue({
        el: '#home-page',
    });
</script>
@stop

Hope this helps

Sign up to request clarification or add additional context in comments.

Comments

1

I just use a single Vue instance.

I have a master blade layout in which the body section looks like the code given below and I extend it for all the pages. It's basically a template with head tag filled with @yield('tags_like_meta', default_value) and some other javascript imports.

<body>
    <div id="app">
        @yield('contents')
    </div>
</body>

And then I have a single Vue instance like this on my js file.

const app=new Vue({el:"#app"});

For different pages I use Vue-router to dynamically load the component. For example, if I want my contact page to be loaded via Vue, I will have my contact_page.blade.php look like this

@extends(layout.master)

@section('contents')
<router-view></router-view>
@endsection

And Vue-router will handle the rendering if I have the contact page url specified in the routes.

Vue.use(VueRouter);

const router = new VueRouter({
    mode: 'history',
    routes: [
        {
            path: '/contact',
            name: 'contact',
            component: () => import('./components/contact/index')
        }]
    });

This way, you can work with single Vue instance (as mentioned in the docs)

2 Comments

Why even use Laravel in this case, if you're doing essentially everything with Javascript? I'm rendering with Laravel
Because I like to keep my backend and frontend separate. Moreover, not everything is done is Javascript. Just the frontend part. The whole backend is in Laravel itself. I use the power of API, so that I can easily build mobile apps using the same Laravel backend code, for literally every projects. And FYI, Laravel is not just rendering the blade template. That's the last stage of returning a response. There are a hell lot of things happening before reaching that point.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.