Laravel, right way to import javascript into Blade Templates
Asked Answered
S

4

50

I am using Laravel 5.6. This page did not work for me.

pizza/index.blade.php looks like this:

@extends('layouts.app')


@section('content')
    <!-- Styles -->
    <link href="{{ asset('css/pizza.css') }}" rel="stylesheet">
    <!-- Scripts -->
    <script src="{{ asset('js/components/pizza.js')}}"></script>
    <div class="container">
        <div class="row justify-content-center">
            <div class="card">
                <div class="card-header">Pizza</div>
                <div class="card-body">
                    <form action="/pizzas" method="post">
                        @if ($errors->any())
                            <div class="alert alert-danger" role="alert">
                                Please fix the following errors
                            </div>
                        @endif
                        @include('pizza.table')
                    </form>
                </div>
            </div>
        </div>
    </div>
@endsection

pizza/table.blade.php:

<div class="pizza-selection">
    <b>Thanks god its pizza day! Select your pizza of the day!</b>
    <table id="pizzas" class="md-box">
        <tr>
            ...
        </tr>
        @foreach ($pizzas as $pizza)
            ...
        @endforeach
        <tr>
            ...
            <input type="button" class="md-box btn btn-default" 
             id="add_new_pizza" onClick="addPizza()" value="Add Pizza!">
            </td>
        </tr>
    </table>
    ...

I get a reference error when I click on the "add_new_pizza" button, onClick="addPizza()", addPizza() is not defined. However, I try to import pizza.js in index.blade.php

<script src="{{ asset('js/components/pizza.js')}}"></script>

printing out asset('js/components/pizza.js') returns http://localhost:8080/js/components/pizza.js which looks right to me.

public/js/components/pizza.js looks like follows:

import PizzaService from '../services/PizzaService.js';

async function addPizza(){
    // some functionality
}

It also worked when I had the function addPizza() inside the script at .blade.php.

Also, find the repository on GitHub if you need any further code reviews: https://github.com/andrelandgraf/laravel-docker

EDIT: When I copy the pizza.js inside <script><script> it works fine, but I receive a SyntaxError: import declarations may only appear at top level of a module. This SyntaxError dissapears when I import the script via src like you can see in my code examples. For me, this indicates that the script is not loaded at all.

EDIT2 & Solution: I used @kerbholz solution. I added @stack('scripts') to the bottom of the body in app.blade.php and inside @section('content') of index.blade.php I know @push('stack') the pizza.js file.

I am now one step further but I still receive the SyntaxError stated in EDIT. Is there a workaround for that or do I just have to remove the import of PizzaService.js and add a <scipt>-Tag for this file as well?

EDIT3: Okay this issue is not related. It looks like ES6 modules are not yet supported by browsers.

Surbased answered 30/7, 2018 at 10:35 Comment(2)
Anything outside of your @section block will not be rendered.Bossuet
@kerbholz thank you very much, I did not know that. I just started using laravel. I edited my question to fix this issue, however I still get the same error messaging.Surbased
B
65

Anything outside of your @section block will not be rendered.

You could edit your layouts/app.blade.php and add a @stack('head') where you want your styles/javascript to appear (preferably in the <head> section of your HTML).

In any blade file that @extends('layouts.app') you can then use

@push('head')
<!-- Styles -->
<link href="{{ asset('css/pizza.css') }}" rel="stylesheet">
<!-- Scripts -->
<script src="{{ asset('js/components/pizza.js')}}"></script>
@endpush

to push content into that stack.

For more information visit https://laravel.com/docs/5.6/blade#stacks

Bossuet answered 30/7, 2018 at 10:42 Comment(8)
Thanks for the reply. I edited my question and put the two scripts inside @section but I still receive the same error. When I try your solution, it disables my css and I receive the same error as before regarding the addPizza function. I also tried to add @stack('scripts') inside the app.blade.php head and pushed to scripts...Surbased
I usually have a @stack('head') in the head and @stack('scripts') at the end of the app.blade.php. The way I would do it is create a file resources/assets/js/_pizza.js and then require('./pizza'); in my app.js. (And of course load app.js in my app.blade.php)Bossuet
Thanks for your supprt @kerbholz. It is now working for me. push('scripts') worked for me!Surbased
It is so annoying, that I cannot reach out to you directly via private message or something. Nevertheless, it was working for me, so I stopped thinking about it but I was wondering since I read your comment. How do you use require('./pizza') within laravel? Out of my knowledge, require is from nodejs and not available in plain js, right?Surbased
@Surbased require is not available in plain JS, right. I think that's from webpack/mix.Bossuet
War mir ein Vergnügen ;)Bossuet
import js file to head is a bad practiceAlyssa
That's why "I usually have a @stack('head') in the head and @stack('scripts') at the end of the app.blade.php." existsBossuet
S
15

For custom scripts on specific page,

  • add @yield('footer-scripts') to layouts/app.blade.php

  • create a folder named 'scripts' in views folder

  • inside views/scripts folder create a file 'pizza-script.blade.php' and add the js file contents inside

    <script src="/path/to/pizza.js" />   <!-- it might not work if path isn't clear -->
    
    <script type="text/javascript">
        console.log('executing js here..')
       js file contents....
    
      #if jquery needed add it like, 
    
      $(document).ready(function(){
        ...
      }
    </script>
    
  • in your index.blade.php (or the page where you want the scripts to execute) at the end add the script after @endsection

      @section('footer-scripts')
          @include('scripts.pizza-script')
      @endsection
    

now refresh the page, you can see 'executing js here..' on the console.

Sparkle answered 19/10, 2020 at 14:31 Comment(0)
S
2

Try to move pizza.js at the bottom of index.blade.php

    @section('extra-script')

    {{Html::script('js/components/pizza.js')}}

    @endsection

Hope it helps.

Substructure answered 30/7, 2018 at 10:45 Comment(5)
thanks for your reply! I have seen the Html:: before but it is not available inside the blade.php template. Where do you get the Html Class from?Surbased
Your config/app.php should contain following code in providers array 'providers' => [ Collective\Html\HtmlServiceProvider::class, ] and aliases should contain 'aliases' => [ 'Form' => Collective\Html\FormFacade::class, 'HTML' => Collective\Html\HtmlFacade::class, ] You can also add: <script src="{{ asset('js/components/pizza.js')}}"></script> if html does not work.Substructure
I see Laravel Collective is another package that I do not have installed.Surbased
I used asset() now within your solution, I still receive the same error...Surbased
Sure thing but they do not really help: web console says: ReferenceError: addPizza is not defined. onClick localhost:8080/pizzas:1:1Surbased
S
1

To import a library from an external source I wrote this small snippet. You add this in your layouts/app.blade in the footer below the footer scripts.

    @if(isset($externalJs))
        @foreach ($externalJs as $js)
            <script src="{{$js}}"></script>
        @endforeach
    @endif

Then in your blade you use it like this at the top of your file:

<?php
$externalJs[] = 'path/to/external.js';
?>

There could be other ways to do it but this is quick one for when you only have one file and dont want to import a librar

Strontian answered 19/1, 2022 at 12:49 Comment(1)
I usually use @section('scripts-bottom') <script></script> @append if you need to add scripts multiple times, maybe from components too, you should use "@append" instead of "@endsection"Magellan

© 2022 - 2024 — McMap. All rights reserved.