Passing a PHP variable to JavaScript in a Blade template - javascript

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']) !!}
{!! 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.

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>

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>
Displaying unescaped data - Laravel docs
json_encode - PHP docs
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>
Blade Templates - Laravel 5.5 docs
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>
Serializing to JSON - Laravel docs

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.

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.

$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

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

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!

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

For me in Laravel v9.2 has this worked.
<script> const something_var = <?php echo json_encode($example->something) ?>;</script>

View
<script>
var langs = JSON.parse({!! json_encode($langs) !!});
</script>

It's Simple and It worked for me...
Just pass the PHP variable into single quotes...
<script>
var collection = '{{ $collection }}';
</script>

Related

Laravel - JS : search function without reloading page, return html

on a small project using laravel and javascript, I would like to implement a search functionality
For this, I would like that once the search is submitted, the page content changes without reloading
So I have a first method in my controller, which renders the page view complete with my data
In the page template, I included a file of partials, containing only my foreach loop and the associated html
Here is the controller method
public function __invoke(MyService $myService)
{
return view('posts.index', [
'posts' => $myService->getAll(),
]);
}
and my partials present in posts.index
#foreach($posts as $post)
<div class="">
{{ $post->name }}
<p class="my-4">
{{ str($post->data)->limit(150) }}
</p>
</div>
#endforeach
So, in my posts.index, I add this JS
var search = document.getElementById("search");
var by = document.getElementById("by");
var form = document.getElementById("form");
form.addEventListener("submit", function(evt) {
evt.preventDefault();
fetch('/search?search=' + search.value + '&by=' + by.value)
.then(response => response.json())
.then(data => {
var elem = document.querySelector('#result');
elem.innerHTML = JSON.stringify(data.html)
});
});
The #result element is where I'm including the partials
There is my search function
public function search(Request $request){
$by = $request->input('by');
switch ($by){
case 'name':
$service = new MyService();
$result = $service->getPostsForName($request->input('search');
$html = view('partials.list', ['posts' => compact('result')])->render();
return response()->json(compact('html'));
break;
}
}
The two methods of the controller return me an Array of Post (my model)
But when I run a search I always get the following error
attempt to read property "url" on array in file
I can't understand why, could you help me please ?

How do i pass data from blade to blade file

I try to pass two value from javascript to another blade file after click button to redirect to new window ...Here is my code
ReportCreate.blade.php js
$("#state").on("change", function() {
var id = $(this).val();
console.log(id)
var cuid = document.getElementById("cu").value;
console.log(cuid)
});
</script>
Click button to open new window which is carry two value from javascript
onclick="openNewWindow('{{ route('sla.slaCategoryTreeListScreen') }}')"
slaCategoryTreeListScreen.blade.php
<!DOCTYPE html>
<script>
// how do i retrieve two value from another blade file
</script>
</html>
First, You'll need to send those values when making the request. You can do this with query params passing a second argument on the route() helper:
onclick="openNewWindow('{{ route('sla.slaCategoryTreeListScreen', ['id' => 123, 'cuid' => 456]) }}')"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Then, you get those values in your controller to finally return them to the second blade file:
# MyCoolController.php
public function toMySecondView(Request $request)
{
$id = $request->get('id');
$cuid = $request->get('cuid');
return view('my_cool_second_view', ['id' => $id, 'cuid' => $cuid]);
}
Just then you'll be able to use them in your second view:
# my_cool_second_view.blade.php
<span> ID: { $id } </span>
<span> CUID: { $cuid } </span>

get and save values from one-to-many relationship and use in javascript with Laravel

Controller code is:
$payments = array();
$pays = User::find($userid);
foreach ($pays->payments as $pay) {
$payments = $pay->payment;
}
it gives output as 18000, 19000, 9000 as stored in array.
I'm confused how to pas these values to my blade file and use in the javascript.
I'm getting only the last values of the array when using in JS.
You are overwriting value of $payments use [] to add in array
$payments = array();
$pays = User::find($userid);
foreach ($pays->payments as $pay) {
$payments[] = $pay->payment;
}
return view('myview_name',compact('payments'))
In laravel blade
#foreach($payments as $payment)
<tr> <td>{{$payment}}</td> </tr>
#endforeach
In javascript you can json_encode and JSON.parse to decode it
var payments = <?php echo json_encode($payments) ?>;
console.log(payments);
Use something like:
$payments = array();
$pays = User::find($userid);
foreach ($pays->payments as $pay) {
$payments[] = $pay->payment;
}
Or simpler:
$payments = $pays->payments->pluck("payment");
And then pass it to the view via e.g.
return view('view.name', compact('payments'));
You can then use it in the view as an array.
If you want to pass it into a JS variable you can use:
<script>
var payments = {!! json_encode($payments) !!};
</script>
Try this
<input type="hidden" id="data" value="{{ $payments }}">
In script section
$(document).ready(function() {
data = $('#data').val();
// Myabe u will need to parse the same.
// And then use it accordingly
});
UPDATE
Return the array in json format and use $.parseJSON(data); to retrieve in js.

Use the same data object across multiple templates in Handlebars.js

I want to use the same data object across multiple templates in different contexts, how can I reuse it. By any chance, handlebars partials would be helpful in this situation.
$("document").ready(function(){
var source = $("#homePage-template").html();
var template = Handlebars.compile(source);
var dataPanel = {activites:[
{activity: "Events" , activityRedirect:"#", icon:"fa fa-camera-retro" , imageUrl:"xyz"},
{activity: "Ciriculars" , activityRedirect:"#", icon:"fa fa-paper-plane", imageUrl:"xyz"}
]};
$("#homePage-placeholder").html(template(dataPanel));
$("#another-placeholder").html(template(dataPanel));
});
And here is my template:
<script id="homePage-template" type="text/x-handlebars-template">
<ul>
{{#activites}}
<li><i class="{{icon}}" aria-hidden="true"></i>{{activity}}</li>
{{/activites}}
</ul>
</script>
Another Template
<script id="another-template" type="text/x-handlebars-template">
{{#activites}}
<div>
<img src="{{imageUrl}}"/>
<span>{{activity}}</span>
</div>
{{/activites}}
</script>
Now how can I reuse this data into "another-template", because I want an image and text in that but it renders like "homePage-template" only in form of a list, if anyone has an idea over this!
In order to have a second template you must fetch its HTML source from the DOM and compile it into a template method just as you are doing for the Home Page Template.
var homepage_template_source = $('#homePage-template').html();
var another_template_source = $('#another-template').html();
var homepage_template = Handlebars.compile(homepage_template_source);
var another_template = Handlebars.compile(another_template_source);
You must call the template method for the specific template you wish to render:
$("#homePage-placeholder").html(homepage_template(dataPanel));
$("#another-placeholder").html(another_template(dataPanel));
See this fiddle for an example.

insert db values to a .js file laravel

i have a view,
<div class="square_box col-xs-7 text-right">
<span>Views Today</span>
<div class="number" id="myTargetElement1"></div>
</div>
so i want to pass some values from my database to this .js file the value 90 for instance i want to fetch it from the database
var demo = new CountUp("myTargetElement1", 12.52, 90, 0, 6, options);
demo.start();
please help me out cause am stuck trying to figure out how to use the php query script inside a js file found in the public folder
I would suggest to use the html tag attribute to store the values and then retrieve it in your JavaScript file.
HTML file:
<div class="square_box col-xs-7 text-right">
<span>Views Today</span>
<div class="number" data-value={{$value}} id="myTargetElement1"></div>
</div>
JS file:.
<script>
var value = $('#myTargetElement1').attr('data-value');
var demo = new CountUp("myTargetElement1", 12.52, value, 0, 6, options);
</script>
The easiest thing to do would probably be to use ajax to call a view and display that view inside of your html.
Here is a very crude example.
$.ajax({
url: "/path/to/your/view",
cache: false
})
.done(function( html ) {
$( "#myTargetElement1" ).append( html );
});
You've to use AJAX to fetch your data into your JS code and then use it.
Or you can simply fetch your result from db and pass it to your view.
$value = DB::table('your_table')->get();
return view('some_view', [ 'value' => $value ]);
Then simply just echo it out using {{ blade }} in your view file
<script>
var demo = new CountUp("myTargetElement1", 12.52, {{ $value }}, 0, 6, options);
</script>

Categories