Laravel Blade: What is best practice for adding javascript in blade files? - laravel

I inherited a Laravel project that has many blade files with javascript inside tags within the blade file. The issue is that there is a lot of repetitive JS logic so I'd like to extract the JS and create JS files to include in the blade? Example: <script src="{{ asset('js/components/file.js')}}"></script>
Is this the best practice for blade files or is it expected to be have the JS within the actual file?

First you have to assign where yo want to push scripts in your layout. for example, say layout.blade.php is your main layout file and you want to inject codes after footer. So add
#stack('scripts')
after footer.
Now in your blade file, use #push to inject your code.
#push('scripts')
<script>
// your code
</script>
#endpush
check blade stack for further detail.

I recommend you to maintain a specific section for page-specific javascript.
Please refer the following examples..
Example template.blade.php
<body>
#yield('content')
#include('_partial.scripts')
#yield('page-script')
#include('_partial.footer')
</body>
then
#section('page-script')
<script type="text/javascript">
// your custom script
</script>
#stop

Just wanted to bring some additionnal information, you can also use the defer attribute.
And here with Laravel 8, in webpack.mix.js
mix.js('resources/js/app.js', 'public/js')
.js('resources/js/my-super-amazing-script.js', 'public/js')
And in your main my-layout.blade.php :
...
#yield('javascript')
</body>
Then, in in your specific page :
#extend('my-layout.blade.php')
...
#section('javascript')
<script src="{{ mix('js/my-super-amazing-script.js') }}" defer></script>
#endsection

Related

Laravel - Prevent duplicate script tags when using partials/modals

I have a few update forms that exist on multiple pages. To reduce workload, I have built these forms as partials/modals that can be #included when needed. Some of the forms utilize a mask.js so I also include an #parent for 'scripts' to include the tag.
It works, but I think I may be attempting to load external JS multiple times if two of the forms use the mask.js and are included in the same view blade.
For example:
Main Page
#include('partials.newdate')
#include('partials.olddate')
partials/newdate.blade.php
#section('scripts')
#parent
<script src="/js/jquery.mask.min.js"></script>
#stop
partials/olddate.blade.php
#section('scripts')
#parent
<script src="/js/jquery.mask.min.js"></script>
#stop
both of the partials need this script, but I also would like to avoid loading it on all pages to reduce load times.
Is there something I can do to "check" for jquery.mask.min.js before laravel adds it to the script section?
You could use the once directive
https://laravel.com/docs/9.x/blade#the-once-directive
#once
#push('scripts')
<script>
// Your custom JavaScript...
</script>
#endpush
#endonce

Laravel 5 proper way to require CSS file from view

I've got specific Form component, which is declared as
Form::component('fcRadio', 'components.form.fcradio', ['name', 'options', 'selected' => null]);
and used as
{{ Form::fcRadio('name', $options }}
What I want is somehow attach custom CSS file, so if the page fires this component at least once, the desired CSS file is included to the <head> of my document.
For example, in Joomla it was like
$this->document->addStylesheet('my_awesome_style.css');
Is there any way to achieve the same in Laravel?
UPD:
I've extended the answers below a bit to let it add multiple styles from multiple templates. Finally, it looks like this:
#section('styles')
#parent
{{HTML::style('css/fcradio.css')}}
#stop
It works fine, but if I use the component twice per page, style is also adds twice. How can I allow multiple but unique entries?
So this is typically how I deal with it:
In your folder: resources/views I create a folder called layout. This folder handles the templates for all my pages.
Then I create a file called default.blade.php. In it I put the bulk of the HTML code. Here's an example of how default.blade.php could look (slimmed down, obviously)
<!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">
<title>
#yield('title')
</title>
<link rel="stylesheet" href="{{ asset('css/main.css') }}">
<!-- Additional per-page css -->
#yield('css')
</head>
<body>
#yield('content')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="js/script.js"></script>
<script src="{{ asset('js/bootstrap.min.js') }}"></script>
<!-- Include per-page JS -->
#yield('js')
</body>
</html>
Right, so essentially what we have so far is the #yield() and asset() helpers.
#yield() is special blade syntax that Laravel uses to say, "Okay. Any time a blade view that is inheriting THIS master template calls the section named in this #yield() I will display that content right here.
asset() is a nifty little helper that basically appends your URL structure onto the string you pass it. So if your url is http://MyGreatSite.com and you use asset('js/script.js') it will spit out a fully qualified URL that will work anywhere on the site (http://MyGreatSite.com/js/script.js). asset() is great because you can use it in blade templates that will get sent out as an email and all of the files will work in an email inbox because they are absolute links.
Right. So now we have this master template and we need to use it. So what I do is create another view in the resources/views directory. Lets say we're doing a contact page. I would make contact.blade.php. Now I want to inherit that master template we created. So we do that like so:
#extends('layout.default)
#section('css')
<link rel="stylesheet" href="{{ asset('css/contact.css') }}">
#stop
#section('title')
Contact Us
#stop
#section('content')
<h1>Contact us</h1>
<p>
Contact us via email: contact#mygreatsite.com
</p>
#stop
#section('js')
<script src="{{ asset('js/contact-form.js') }}"></script>
#stop
Okay, so, first things first. At the very top we tell this blade file that we want to use the template we just made. We use the blade helper #extends() and pass it the path to our view relative to the views directory separated by periods.
Next, we want to create the sections that correspond to the template. We do that by opening the section with #section() and passing the name of the section we want to push this block of content to. We write our content and then we close the section by using #stop. Pretty simple. For images, css, or js, we simply use the asset() helper again.
I know it's a little long-winded, but hopefully that helps and explains the process a little better.
tl;dr: Use #yield(), #section(), and asset().
So I think I understand what you are saying.
In your blade layout file create a section inside the head:
<head>
#yield('componentcss')
</head>
And in the component do:
#section('componentcss')
{{HTML::style('css/fcradio.css')}}
#stop
You could also just include the css but I wouldn't advise this:
#section('componentcss')
<style>
.exampleclass {text-align:center;}
</style>
#stop
Hopefully I have understood you correctly.
I've finally found a bit tricky but working solution:
#hasSection('fcRadioStyle')
#else
#section('fcRadioStyle')
{{Html::style('css/components/fcradio.css')}}
#stop
#section('styles')
#yield('fcRadioStyle')
#append
#endif
This makes by Form::fcRadio append this style only once

Laravel 5.2 using #yield and #section

I have 2 parts in my main layout: #yield('styles') #yield('scripts')
In the other template files which extended the main layout,
I use #section('styles') and #section('scripts')
When I am loading partial views, all the styles in the 'styles' sections are loading well. But, about the scripts, only the first partial view's scripts are loading and for the others, it ignores them.
Any Idea or experience before?
have you looked at #stack?
#stack('css') and #stack('scripts') instead of #yeild
you can then do
#push('scripts')
<script> /js/jquery.js</script>
#endpush
That way you can push different scripts or css to the header or footer depending on your template page
https://laravel.com/docs/5.2/blade#stacks

Using include in different situations

I have a boilerplate that has various includes, one being:
#include('nav')
I would like to use the same boilerplate for the CMS of my site, but use a different nav.
What would be the best way of getting the boilerplate to include a different nav when the user is using the CMS:
#include('nav-cms')
This is more of an architectural question, and the answer is that you can probably do this many, many ways. However, the answers can be Laravel specific, so here goes:
One method would be to change the include statement to be:
#include($navView)
And then either in your controller, or using view composer, you should set that variable appropriately.
Alternatively, you can do it using sections:
// layout.blade.php
<html>
<head></head>
<body>
#section('nav')
#include('nav')
#show
#yield('content')
</body>
</html>
// some-frontend-view.blade.php
#extends('layout')
#section('content')
Content here
#stop
// some-cms-view.blade.php
#extends('layout')
#section('nav')
#include('nav-cms')
#overwrite
#section('content')
CMS content here
#stop
That way it assumes frontend nav, and then you override it in the CMS for the CMS nav. Alternatively, instead of defaulting to 'nav' in the layout, you could use #yield, and specify it in the some-frontend-view.blade.php file as in the some-cms-view.blade.php file.

Include a view with javascript functionality

I want to #include a view in my main view. The thing is I've wrote sοme javascript code to interact with that piece of code. Is there a way to include both html and javascript code, since for the second one I have to add <script> tag? I #include this view in many files so I don't want to hardcoded.
Here's three options of things you can do, but there are plenty more:
<html><body>
<!-- A javascript to be added by a particular view-->
<script type="text/javascript">
#yield('in-view-javascript')
</script>
<!-- A javascript only files, no script tag-->
<script type="text/javascript">
#include('views._partials.javascript-1')
#include('views._partials.javascript-2')
#include('views._partials.javascript-3')
</script>
<!-- A javascript code with script tag-->
#include('views._partials.javascript-code')
</body></html>
In views you can
#section('in-view-javascript')
console.log('in-view-javascript');
#stop
Or you can include another javascript file here:
#section('in-view-javascript')
#include('views._partials.javascript')
#stop
Your javascript-1, javascript-2, javascript-3 would be just javascript without the <script> tag.
And javascript-code would be a full javascript code, including the tag.

Resources