Jenssen
Jenssen

Reputation: 1871

Vue.js 2.0 failed to compile template

I use webpack, vue.js 2.0 and Laravel 5.3. Nothing goes wrong when I compile with gulp.

But I get this error in the console when I go to /home that links to home.blade.php.

Error:

vue.js?3de6:515 [Vue warn]: failed to compile template:

//my component

(found in root instance) 

app.js

require('./bootstrap');


Vue.component('CheckoutForm', require('./components/CheckoutForm.vue'));

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

app.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Laravel') }}</title>

    <!-- Styles -->
    <link href="/css/app.css" rel="stylesheet">

    <!-- Scripts -->
    <script>
        window.lnj = <?php echo json_encode([
            'csrfToken' => csrf_token(),
            'stripeKey' => config('services.stripe.key')
        ]); ?>
    </script>
</head>
<body>
    <div id="app">
        <nav class="navbar navbar-default navbar-static-top">
            <div class="container">
                <div class="navbar-header">

                    <!-- Collapsed Hamburger -->
                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#app-navbar-collapse">
                        <span class="sr-only">Toggle Navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>

                    <!-- Branding Image -->
                    <a class="navbar-brand" href="{{ url('/') }}">
                        {{ config('app.name', 'Laravel') }}
                    </a>
                </div>

                <div class="collapse navbar-collapse" id="app-navbar-collapse">
                    <!-- Left Side Of Navbar -->
                    <ul class="nav navbar-nav">

                    </ul>

                    <!-- Right Side Of Navbar -->
                    <ul class="nav navbar-nav navbar-right">
                        <!-- Authentication Links -->
                        @if (Auth::guest())
                            <li><a href="{{ url('/login') }}">Login</a></li>
                            <li><a href="{{ url('/register') }}">Register</a></li>
                        @else
                            <li class="dropdown">
                                <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
                                    {{ Auth::user()->name }} <span class="caret"></span>
                                </a>

                                <ul class="dropdown-menu" role="menu">
                                    <li>
                                        <a href="{{ url('/logout') }}"
                                            onclick="event.preventDefault();
                                                     document.getElementById('logout-form').submit();">
                                            Logout
                                        </a>

                                        <form id="logout-form" action="{{ url('/logout') }}" method="POST" style="display: none;">
                                            {{ csrf_field() }}
                                        </form>
                                    </li>
                                </ul>
                            </li>
                        @endif
                    </ul>
                </div>
            </div>
        </nav>

        @yield('content')
    </div>

    <!-- Scripts -->
    <script src="https://checkout.stripe.com/checkout.js"></script>
    <script src="/js/app.js"></script>
</body>
</html>

home.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Dashboard</div>

                <div class="panel-body">
                    <checkout-form :plans="{{ $plans }}"></checkout-form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

package.json

{
  "private": true,
  "scripts": {
    "prod": "gulp --production",
    "dev": "gulp watch"
  },
  "devDependencies": {
    "bootstrap-sass": "^3.3.7",
    "gulp": "^3.9.1",
    "jquery": "^3.1.0",
    "laravel-elixir": "^6.0.0-14",
    "laravel-elixir-vue-2": "^0.2.0",
    "laravel-elixir-webpack-official": "^1.0.2",
    "lodash": "^4.16.2",
    "vue": "^2.0.1",
    "vue-resource": "^1.0.3"
  }
}

checkoutForm.js (component)

<template>
    <form action="/subscriptions" method="POST">
        <select name="plans" v-model="plan">
            <option v-for="plan in plans" :value="plan.id">
                {{ plan.plan }} &mdash; {{ plan.price / 100 }}
            </option>
        </select>

        <button type="submit" @click.prevent="subscribe">Koop het hier!</button>

        <p v-show="status" v-text="status"></p>
    </form>
</template>

<script>
    export default {
        props: ['plans'],

        data() {
            return {
                stripeEmail: '',
                stripeToken: '',
                status: false,
                plan: 1
            };
        },

        created() {
            this.stripe = StripeCheckout.configure({
                key: lnj.stripeKey,
                locale: "auto",
                panelLabel: "Subscribe For",
                token: (token) => {
                    this.stripeToken = token.id;
                    this.stripeEmail = token.email;

                    this.$http.post('/subscriptions', this.$data)
                            .then(
                                response => alert("Success!"),
                                response => this.status = response.body.status
                            );
                }
            });
        },

        methods: {
            subscribe() {
                let plan = this.findPlanById(this.plan);
                this.stripe.open({
                        'Name': plan.name,
                        'description': plan.description,
                        'zipCode': true,
                        'currency': "eur",
                        'amount': plan.price
                });
            },

            findPlanById(id) {
                return this.plans.find(plan => plan.id == id);
            }
        }
    }
</script>

What could be the problem?

Upvotes: 2

Views: 10112

Answers (2)

Jetmir Haxhisefa
Jetmir Haxhisefa

Reputation: 13

Make sure that the $plans is set (is not null) in your home.blade.php

Upvotes: 0

GuyC
GuyC

Reputation: 6574

First ensure you haven't named your component checkoutForm.js when it should be checkoutForm.vue otherwise webpack will use the incorrect loaders.

Within your main app.js you need to rename your component to lowercase hyphenated:

Vue.component('checkout-form' ...

Then you are setting this.stripe to an instance of StripeCheckout

instead you should:

checkoutForm.js

data() {
   return {
      stripeEmail: '',
      stripeToken: '',
      status: false,
      plan: 1
   };
},

stripe: null,

created() {
   this.$options.stripe = StripeCheckout.configure({
   ...

Then always reference this.$options.stripe otherwise Vue will try and make stripe reactive

Upvotes: 2

Related Questions