69

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.

miken32
  • 42,008
  • 16
  • 111
  • 154
user1610851
  • 691
  • 1
  • 5
  • 6

11 Answers11

126

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>
ken
  • 13,869
  • 6
  • 42
  • 36
  • 3
    You may want to add JSON_HEX_TAG to json_encode `{!! json_encode($sites->toArray(), JSON_HEX_TAG) !!};` http://stackoverflow.com/questions/24855186/most-efficient-way-to-pass-php-variables-to-external-javascript-or-jquery-file – Jon Apr 18 '17 at 22:27
  • @ken 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? – Agil Jul 11 '18 at 10:48
  • nvm, I didn't realise that i didnt need the quotes when using `json_encode` – Agil Jul 11 '18 at 10:51
  • 5
    or just `var sites = @json($sites->toArray())` – Илья Зеленько Sep 14 '18 at 06:04
  • weird I was doing var sites = "{!! json_encode($sites->toArray()) !!}"; with quotes and it no work, ty. – Andrew Nov 04 '18 at 17:36
  • 1
    @Andrew you can remove the double quote and try again. – ken Nov 05 '18 at 06:39
  • hi @ken. can u hrlp me in that question https://stackoverflow.com/q/75150981/14913109 – Hamza Qureshi Jan 17 '23 at 19:56
47

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>
algorhythm
  • 8,530
  • 3
  • 35
  • 47
  • 1
    The best way according with what? – Rafael Soufraz Jun 11 '18 at 15:46
  • According to use huge libraries or directly responding it to the client which is an often seen solution. – algorhythm Jun 12 '18 at 05:13
  • Worth noting [not all valid JSON are valid JavaScript (old version)](https://stackoverflow.com/questions/23752156/are-all-json-objects-also-valid-javascript-objects), but PHP seems to always escape `"\u2029"` even with `JSON_UNESCAPED_LINE_TERMINATORS| JSON_UNESCAPED_UNICODE` so this should be safe regardless. – user202729 Aug 14 '23 at 02:44
16

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.

JCarlosR
  • 1,598
  • 3
  • 19
  • 32
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.

Dan
  • 131
  • 2
  • 6
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

Pawel Bieszczad
  • 12,925
  • 3
  • 37
  • 40
  • 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-object – user1610851 May 06 '15 at 15:13
  • can you post the code on that line and anything relevant to it? – Pawel Bieszczad May 06 '15 at 15:17
  • 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 ]); – user1610851 May 06 '15 at 15:17
  • 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 javascript – Pawel Bieszczad May 06 '15 at 15:21
  • 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. – user1610851 May 07 '15 at 01:29
  • 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. – Pawel Bieszczad May 07 '15 at 05:26
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
Nelson Sammy
  • 404
  • 2
  • 7
  • 16
PHANTOM-X
  • 502
  • 6
  • 16
2

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

For anyone else still struggling.

James Christian Kaguo
  • 1,251
  • 15
  • 14
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!

Radames E. Hernandez
  • 4,235
  • 27
  • 37
-1

View

<script>  
       var langs = JSON.parse({!! json_encode($langs) !!});
</script>
user2462948
  • 87
  • 1
  • 5
-1

For me in Laravel v9.2 has this worked.

<script> const something_var = <?php echo json_encode($example->something) ?>;</script>
lortschi
  • 2,768
  • 2
  • 18
  • 12
-3

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

Just pass the PHP variable into single quotes...

<script>
    var collection = '{{ $collection }}';
</script>