ArchStanton's avatar

Including Js files on per route basis?

Hi,

Has anyone got any neat solutions for this, I would like to add my js only on certain routes, I have a pages controller so maybe something from there? Any nice elegant solutions are warmly welcomed.

0 likes
9 replies
mstnorris's avatar

@LeBlaireau Why not add them in the views?

In your master view add a yield right at the bottom before the closing body tag.

master.blade.php

<html>
<head>
<title>Your Title</title>
<link href="/css/main.css" ref="stylesheet"> // including standard css across all pages
@yield('header') // getting page-specific content such as custom styles
</head>
<body>

@yield('content') // including your main content

<script src="/js/main.js"></script> // including standard script across all pages

@yield('footer') // getting page-specific content such as custom scripts

</body>
</html>

And then on the pages that you need to add extra JavaScripts, you can by including a footer section like so:

page.blade.php

@extends('master')

@section('header')
// your extra stylesheets here, as well as anything else you want to include before the rest of the page loads
@endsection

@section('content')
// your main content here
@endsection

@section('footer')
// your extra scripts here
<script src="..."></script>
@endsection
1 like
toniperic's avatar

@LeBlaireau as I see it, you can just place it in the view file itself.

But, since you've specified you want to add JS only on certain routes, and same view file can be used for many routes, then you could just pass an array of Javascript files to the view you'd like to include, like this:

function foo()
{
    $js = ['bar.js', 'baz.js'];

    return view('some.view', compact('js'));
}

and then in your view file

@if(isset($js))
    @foreach($js as $file)
        // include your js file here
    @endforeach 
@endif

That would be a quick soluton. However if you're using the same approach of including JS files throughout your whole app, you might think about leveraging view composer, so the $js variable is present in every view, so you don't have to check if it has been set. Then, you can include the following code in all of your views

@foreach($js as $file)
    // include your js file here
@endforeach

and then whenever you want to provide a JS file to a certain view, you can do so from your controller method.

mstnorris's avatar

As one route will show one view, then your best bet is to add the JavaScript to the view, there isn't any benefit in passing it via the controller. It will only confuse things as it won't be clear "where" the JavaScript is coming from.

toniperic's avatar

I agree with @mstnorris though. Controllers shouldn't have to know at all what Javascript files have to be included for what view. It's probably a bad code design decision made earlier that led to posting such a question.

1 like
andy's avatar
andy
Best Answer
Level 8

I tend to include specific css and js on per view basis.


@section('styles')
    <link rel="stylesheet" href="{{ asset('assets/vendors/bootstrap-datepicker/css/datepicker3.css') }}">
    <link rel="stylesheet" href="{{ asset('assets/vendors/chosen_v1.0.0/chosen.min.css') }}">
    <link rel="stylesheet" href="{{ asset('assets/vendors/chosen_v1.0.0/chosen_bootstrap.css') }}">
@stop

@section('scripts')
    <script src="{{ asset('assets/vendors/bootstrap-datepicker/js/bootstrap-datepicker.js') }}"></script>
    <script src="{{ asset('assets/vendors/bootstrap-datepicker/js/datepicker-settings.js') }}"></script>
    <script src="{{ asset('assets/vendors/chosen_v1.0.0/chosen.jquery.min.js') }}"></script>
@stop
@section('inline-scripts')
$(document).ready(function(){

    var config = {
        '.chosen-select'           : {},
        '.chosen-select-deselect'  : {allow_single_deselect:true},
        '.chosen-select-no-single' : {disable_search_threshold:10},
        '.chosen-select-no-results': {no_results_text:'Oops, nothing found!'},
        '.chosen-select-width'     : {width:"95%"}
    }
    for (var selector in config) {
        $(selector).chosen(config[selector]);
    }

});
@stop

Then in my master/default view:

<!-- ------------------------------------------ app loaded js ------------------------------------------ -->
    @yield('scripts')

<!-- ------------------------------------------ template loaded js ------------------------------------------ -->
    <script type="text/javascript">
        @yield('inline-scripts')
    </script>

I haven't really looked into speed issues but these views are not normally heavy traffic areas.

mstnorris's avatar

@andy that is essentially the same as my answer, however you're not limited to just styles and scripts (obviously neither is your way), it's just your naming convention is / could be, a little off if you needed to include something other than style and scripts.

@LeBlaireau if that has answered your question, please mark it :)

pmall's avatar

same view file can be used for many routes

I think it is a bad idea. You can share common html with layouts and do some fine tuning with individual views.

andy's avatar

@mstnorris Yes, our techniques do look similar. Hmm, gonna play around with adding another partial to the mix. My main app.blade is starting to get too long.

Thanks for bringing your post to my attention.

mstnorris's avatar

@andy You're welcome. My approach allows for extensibility and helps to reduce the size of the master page.

Please or to participate in this conversation.