Passing a PHP variable to JavaScript in a Blade template
Asked Answered
L

10

78

is there any ways that JavaScript can get the variable from the controller in a Laravel Blade template?

Example: I have the code below:

$langs = Language::all();
return View::make('NAATIMockTest.Admin.Language.index',compact('langs'));

Can I get $langs and pass it to JavaScript? I already used PHP-Vars-To-Js-Transformer. But when I use JavaScript::put() for two functions in the controller. It didn't work. Any help?

This is my create function in the controller:

public function create()
{
    $names = $this->initLang();
    Javascript::put([
        'langs' => $names
    ]);
    
    return View::make('NAATIMockTest.Admin.Language.create',compact('names'));
}

this is my view:

@extends('AdLayout')
@section('content')
<script type="text/javascript">
    var app = angular.module('myApp', []);
    app.controller('langCtrl', function($scope) {
        $scope.languages = langs;
    });
</script>
    
<div class="container-fluid" ng-app="myApp" ng-controller="langCtrl">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">
                    <h2>Create language</h2>
                </div>
                    
                <div class="panel-body">
                    {!! Form::open() !!}
                        <p class="text-center">
                            {!! Form::label('Name','Language: ') !!}
                            <input type="text" name="searchLanguage" ng-model="searchLanguage">
                        </p>
    
                        <select name="Name[]" multiple size="10" ng-model="lang" ng-click="show()">
                            <option value="@{{v}}" ng-repeat="(k,v) in languages | filter:searchLanguage">
                                @{{v}}
                            </option>
                        </select><br>
    
                        <div class="text-center">
                            {!! Form::submit('Create',['class'=>'btn btn-primary']) !!}&nbsp;
                            {!!   Html::linkAction('NAATIMockTest\LanguageController@index', 'Back', null, array('class' => 'btn btn-primary')) !!}
                        </div>
                    {!! Form::close() !!}
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

my javascript.php in config folder:

<?php
return [
    'bind_js_vars_to_this_view' => 'footer',
    'bind_js_vars_to_this_view' => 'NAATIMockTest.Admin.Language.create',
    'bind_js_vars_to_this_view' => 'NAATIMockTest.Admin.Language.edit',
    
    'js_namespace' => 'window',
];

The idea is: I have a table language in MySQL. I want to show the dropdown list with multiple attributes to choose, and I also want to search with angularjs as well. That's why I want to pass the variable from the controller to JavaScript. Additionally, I have the function inside LanguageController called initLang to check if any language is exist inside the database, it isn't displayed inside the dropdown list in create the view.

Lid answered 6/5, 2015 at 10:27 Comment(6)
can you also show how you wish to use langs in your javacript code?Extensor
Since you are already using a package, please show us the code that doesn't work. (edit your question)Horsy
Maybe the two functions did render the view or partial, you have chosen to bind the javascript variables to?Volleyball
it only works for edit view, but for a create view i doesn't work at all. i wanna use angularjs to search instead of using laravelLid
Check this.Dorathydorca
Try this - github.com/laracasts/PHP-Vars-To-Js-Transformer Is simple way to append PHP variables to Javascript.Swagsman
B
129

One working example for me.

Controller:

public function tableView()
{
    $sites = Site::all();
    return view('main.table', compact('sites'));
}

View:

<script>    
    var sites = {!! json_encode($sites->toArray()) !!};
</script>

To prevent malicious / unintended behaviour, you can use JSON_HEX_TAG as suggested by Jon in the comment that links to this SO answer

<script>    
    var sites = {!! json_encode($sites->toArray(), JSON_HEX_TAG) !!};
</script>
Bronchiole answered 3/7, 2015 at 7:32 Comment(7)
You may want to add JSON_HEX_TAG to json_encode {!! json_encode($sites->toArray(), JSON_HEX_TAG) !!}; #24855686Sculpture
@Bronchiole Oh this actually does work, but there are quotes in the beginning and at the end of the html. How can I get rid of them?Domoniquedomph
nvm, I didn't realise that i didnt need the quotes when using json_encodeDomoniquedomph
or just var sites = @json($sites->toArray())Fisken
weird I was doing var sites = "{!! json_encode($sites->toArray()) !!}"; with quotes and it no work, ty.Irk
@Irk you can remove the double quote and try again.Bronchiole
hi @ken. can u hrlp me in that question https://mcmap.net/q/73249/-what-is-the-difference-between-client-side-and-server-side-programming/14913109Abdominous
P
48

Standard PHP objects

The best way to provide PHP variables to JavaScript is json_encode. When using Blade you can do it like following:

<script>
    var bool = {!! json_encode($bool) !!};
    var int = {!! json_encode($int) !!};
    /* ... */
    var array = {!! json_encode($array_without_keys) !!};
    var object = {!! json_encode($array_with_keys) !!};
    var object = {!! json_encode($stdClass) !!};
</script>

There is also a Blade directive for decoding to JSON. I'm not sure since which version of Laravel but in 5.5 it is available. Use it like following:

<script>
    var array = @json($array);
</script>

Jsonable's

When using Laravel objects e.g. Collection or Model you should use the ->toJson() method. All those classes that implements the \Illuminate\Contracts\Support\Jsonable interface supports this method call. The call returns automatically JSON.

<script>
    var collection = {!! $collection->toJson() !!};
    var model = {!! $model->toJson() !!};
</script>

When using Model class you can define the $hidden property inside the class and those will be filtered in JSON. The $hidden property, as its name describs, hides sensitive content. So this mechanism is the best for me. Do it like following:

class User extends Model
{
    /* ... */

    protected $hidden = [
        'password', 'ip_address' /* , ... */
    ];

    /* ... */
}

And somewhere in your view

<script>
    var user = {!! $user->toJson() !!};
</script>
Protestantism answered 6/7, 2017 at 17:12 Comment(3)
The best way according with what?Roots
According to use huge libraries or directly responding it to the client which is an often seen solution.Protestantism
Worth noting not all valid JSON are valid JavaScript (old version), but PHP seems to always escape "\u2029" even with JSON_UNESCAPED_LINE_TERMINATORS| JSON_UNESCAPED_UNICODE so this should be safe regardless.Seamstress
A
17

Let's say you have a collection named $services that you are passing to the view.

If you need a JS array with the names, you can iterate over this as follows:

<script>
    const myServices = [];
    @foreach ($services as $service)
        myServices.push('{{ $service->name }}');
    @endforeach
</script>

Note: If the string has special characters (like ó or HTML code), you can use {!! $service->name !!}.

If you need an array of objects (with all of the attributes), you can use:

<script>
  const myServices = @json($services);
  // ...
</script>

Note: This blade directive @json is not available for old Laravel versions. You can achieve the same result using json_encode as described in other answers.


Sometimes you don't need to pass a complete collection to the view, and just an array with 1 attribute. If that's your case, you better use $services = Service::pluck('name'); in your Controller.

Assembly answered 15/1, 2017 at 19:44 Comment(2)
Why not using var sampleTags = [{{ $services->implode(',') }}]; or similar?Protestantism
As I remember, latest versions of Laravel have also a blade directive that simplifies it like @json($services).Assembly
T
11

2022

Laravel has been updated so this can now be simplified to:

<script>const langs = {{ Js::from(Language::all()) }};</script>

Or, for any PHP object:

<script>const jsObject = {{ Js::from($phpObject) }};</script>

This also adds the JSON_HEX_TAGs mentioned in Ken's answer.

Taylor answered 19/5, 2022 at 20:2 Comment(1)
Supported in v8 as well laravel.com/docs/8.x/blade#rendering-jsonWorked
P
5
$langs = Language::all()->toArray();
return View::make('NAATIMockTest.Admin.Language.index', [
    'langs' => $langs
]);

then in view

<script type="text/javascript">
    var langs = {{json_encode($langs)}};
    console.log(langs);
</script>

Its not pretty tho

Plate answered 6/5, 2015 at 14:43 Comment(6)
thanks for your code but it shows me this problem: FatalErrorException in LanguageController.php line 34: Call to a member function toArray() on a non-objectLid
can you post the code on that line and anything relevant to it?Plate
this error is Undefined variable: langs (View: /home/thienvulai/laravel/sls/resources/views/NAATIMockTest/Admin/Language/create.blade.php). When i tried to use Javascript::put([ 'langs' => $names ]);Lid
my code isnt using the Javascript class. If you just create a test method in your controller with my code only, and then comment everything else in the view except for my code you should see the langs object in the console. You can then use the langs variable in the javascriptPlate
Thanks Pawel Bieszczad, The Alpha and everyone who tries to fix my problem. I've just woke up. Yeah i did try your code Pawel Bieszczad but its so me the problems: "uncaught SyntaxError: Unexpected token &". And I'm doing with laravel-5 not laravel-4 so the file filters.php is not exist. So what should i do.Lid
Do you have any other JavaScript files loaded in that view? Try excluding any other code in the controller, JavaScript and view, just to see if you get the desired output.Plate
O
3

The best way is to put it in a hidden div in php blade

<div hidden id="token">{{$token}}</div>

then call it in javascript as a constant to avoid undefined var errors

const token = document.querySelector('div[id=token]').textContent

// console.log(token)
// eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiI5MjNlOTcyMi02N2NmLTQ4M2UtYTk4Mi01YmE5YTI0Y2M2MzMiLCJqdGkiOiI2Y2I1ZGRhNzRhZjNhYTkwNzA3ZjMzMDFiYjBiZDUzNTZjNjYxMGUyZWJlNmYzOTI5NzBmMjNjNDdiNjhjY2FiYjI0ZWVmMzYwZmNiZDBmNyIsImlhdCI6IjE2MDgwODMyNTYuNTE2NjE4IiwibmJmIjoiMTYwODA4MzI1Ni41MTY2MjUiLCJleHAiOiIxNjIzODA4MDU2LjMxMTg5NSIsInN1YiI6IjUiLCJzY29wZXMiOlsiYWRtaW4iXX0.GbKZ8CIjt3otzFyE5aZEkNBCtn75ApIfS6QbnD6z0nxDjycknQaQYz2EGems9Z3Qjabe5PA9zL1mVnycCieeQfpLvWL9xDu9hKkIMs006Sznrp8gWy6JK8qX4Xx3GkzWEx8Z7ZZmhsKUgEyRkqnKJ-1BqC2tTiTBqBAO6pK_Pz7H74gV95dsMiys9afPKP5ztW93kwaC-pj4h-vv-GftXXc6XDnUhTppT4qxn1r2Hf7k-NXE_IHq4ZPb20LRXboH0RnbJgq2JA1E3WFX5_a6FeWJvLlLnGGNOT0ocdNZq7nTGWwfocHlv6pH0NFaKa3hLoRh79d5KO_nysPVCDt7jYOMnpiq8ybIbe3oYjlWyk_rdQ9067bnsfxyexQwLC3IJpAH27Az8FQuOQMZg2HJhK8WtWUph5bsYUU0O2uPG8HY9922yTGYwzeMEdAqBss85jdpMNuECtlIFM1Pc4S-0nrCtBE_tNXn8ATDrm6FecdSK8KnnrCOSsZhR04MvTyznqCMAnKtN_vMDpmIAmPd181UanjO_kxR7QIlsEmT_UhM1MBmyfdIEvHkgLgUdUouonjQNvOKwCrrgDkP0hkZQff-iuHPwpL-CUjw7GPa70lp-TIDhfei8T90RkAXte1XKv7ku3sgENHTwPrL9QSrNtdc5MfB9AbUV-tFMJn9T7k
Ordonnance answered 16/12, 2020 at 14:9 Comment(1)
Underrated answer, this is the correct way.Genesisgenet
C
3

if it's an array you may want to write it like this JSON.parse('{!! json_encode($months) !!}')

For anyone else still struggling.

Crowned answered 12/8, 2022 at 14:44 Comment(0)
L
1

Is very easy, I use this code:

Controller:

$langs = Language::all()->toArray();
return view('NAATIMockTest.Admin.Language.index', compact('langs'));

View:

<script type="text/javascript">
    var langs = <?php echo json_decode($langs); ?>;
    console.log(langs);
</script>

hope it has been helpful, regards!

Lungfish answered 7/6, 2018 at 0:4 Comment(0)
B
-1

For me in Laravel v9.2 has this worked.

<script> const something_var = <?php echo json_encode($example->something) ?>;</script>
Banquette answered 2/2, 2023 at 20:53 Comment(0)
A
-3

It's Simple and It worked for me...

Just pass the PHP variable into single quotes...

<script>
    var collection = '{{ $collection }}';
</script>
Approve answered 4/8, 2021 at 18:2 Comment(1)
This won't work if the value has single quotes in it.Institutionalism

© 2022 - 2024 — McMap. All rights reserved.