How to pass javascript variable from laravel controller to vuejs component - laravel

I'm trying to build a page on Laravel 5.4 which contains few data which needs to be manipulated and then sent across the views. My view contains components of the vuejs v2.0. I want those data to be implemented in the components. I tried using the laracasts PHP Vars to JS transformer but unable to get it. I followed the steps by placing "laracasts/utilities": "~2.0" in my composer.json then I added the serviceprovider as mentioned in the documentation, I published the vendor and added the following in config/javascript.php,
'bind_js_vars_to_this_view' => 'Nitseditor.show',
I'm having a dynamic views folder which is currently inside my Nitseditor\home\resources\views Now in my controller I'm having following codes:
public function show()
{
JavaScript::put([
'foo' => 'bar',
'age' => 29
]);
return view(Nitseditor.show);
}
Now first of all it was throwing an error as I see that it was including use MongoDB\BSON\Javascript; then I removed and tried using use JavaScript
Now in the app.js file which is present in my asset folder, I'm including each components and trying to do console.log(foo); but its throwing an error foo not defined.

There are a few ways to do this depending on what you are trying to achieve and how your project is set up. The simplest way is to make a request to your controller from inside your component that returns json. Laravel 5.4 comes with axios so you can use that:
methods: {
getData(){
axios.get('/controller/route')
.then(response => {
// set your variables from the response
this.myData = response.data;
})
.catch(error => {
console.log(error);
});
},
data(){
return {
myData: {}
}
}
If you need child components to access the data then you would need to put that in the parent and pass myData" using props.
You could also create a directive and pass your variable down directly from your blade template:
Vue.directive('init', {
bind: function(el, binding, vnode) {
vnode.context[binding.arg] = binding.value;
}
});
Then you would just need to do:
<div v-init:vars="{foo: 'foo', age: 29}"></div>
And pass vars as props to any component that needs them:
Here's the JSFiddle: https://jsfiddle.net/3e05qwLh/
If you have multiple descendants that rely on your variables you will probably want to look at using vuex.

Dunno if it helps but I use this method for passing variables to javascript:
// in master layout (head section)
<meta name="foo" content="{{ $foo }}">
// in javascript (included or in the template)
foo = $('meta[name=foo]').attr('content');
If you have javascript in the blade template you can use directly this method:
foo = "{{ $foo }}";

Related

laravel passing a variable to js file from a controller

I have a js file located in assets folder (not View). can i pass a varible from a controller?
In view file:
The Js is called like this
<canvas id="chart1" class="chart-canvas"></canvas>
</div>
It is not possible (in my point of view) to put a variable to external JS file. You can use data-... attributes and get values from html elements.
For example you can pass your PHP variable as a json encoded string variable in your controller.
$data['chart_info'] = json_encode($chart_info);
return view('your_view', $data);
Then put it in data-info like this.
<canvas id="chart1" class="chart-canvas" data-info="{{ $chart_info }}"></canvas>
And finally in JS, you can get the variable and decode (parse) it as following.
let canvas = document.getElementById('chart1');
let info = JSON.parse(canvas.dataset.id);
console.log(info);
You can put that part of the Javascript in the view and send the variable to the same view. For example, add a section in view:
#section('footer')
<script type="text/javascript">
</script>
#endsection
Do not forget that you should add #yield('footer') to the end of your layout view.
I don't like to mix javascript and PHP/Blade, it might be hard to read the code in the future... You could use a different approach, loading the chart with a async ajax request.
You will have to create a end-point that returns the data you need for your chart:
Your router:
Route::get('/chart/get-data', [ ControllerName::class, 'getChartData' ]);
Your controller method:
public function getChartData() {
$chartData = [];
// Your logic goes here
return $chardData;
}
In your javascript (using jquery) file there will be something like that:
function loadChartData() {
$.ajax({
'url': '/chart/get-data',
'method': 'GET'
})
.done((data) => {
// Load your chart here!!!
})
.fail(() => {
console.log("Could not load chart data");
});
}
Hope I helped ;)

Vue2 + laravel6 - Component implementation

I just started using Vue2 with Laravel6 and got stuck when trying to understand how to use component method.
As I am totally new for Vue, I am using the official tutorial of Vue as a reference. What I learned from here(https://v2.vuejs.org/v2/guide/components.html) about Vue component instantiation is we give options to a component.(e.g. we give 'template:' options for HTML part.)
When I look at laravel6 codes of resouces/js/app.js, it looks something like this:
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
I looked at js/components/ExampleComponent.vue expecting to see some options declared there. However, there's no option in the ExampleComponent.vue file. Instead, I see <template></template> tag. Apparently, the <template></template> tag seems to work as 'template:' option.
I have two questions regarding above:
Does <template></template> tag have the same meaning as 'template:' option?
If question 1 is yes, are other options also replacable with corresponding tags? (e.g. Can I use <props></props> tag for 'props:' option? or <data></data> tag for 'data:' option?
Thanks in advance!
In Vue world, there are two popular types of defining a component
First Type
in this type, you add all of your HTML inside the template property
and the props add as attribute inside the component object to
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
Second Type
in this type you add your component logic in a separate file ends with .vue
for example in laravel there is an ExampleComponent.vue file you will find on
it just template tag just as a wrapper for your component content and your logic you can write it as it mentions below.
<template>
// some content here
</template>
<script>
export default {
props: [],
methods: {
},
data(){
return {
}
}
}
</script>
Finally
there is no tag called props or data
for more info read this article

How to pass an object from Laravel to Vue without using props

I'm setting up some Vue Components in my Laravel 5.8 application, that require user information available through Auth::user(), most importantly, the api_token that I must use in my axios requests. I want to pass the Auth::user() object from Laravel to Vue in a secure and private method.
I initially passed the object as props, but I don't want private information on the object to be easily exposed using browser extensions such as Vue DevTools. Now, I've been searching for a way to define global variables inside the Blade Template and access them in Vue:
Pass data from blade to vue component
https://forum.vuejs.org/t/accessing-global-variables-from-single-file-vue-component/638
https://zaengle.com/blog/layers-of-a-laravel-vue-application
Based on those links above, it seems like what I need to do is set the variables to the window object, but I'm unsure on what I'm doing something wrong to achieve this. When I define the variable in the Blade Template, I can see the variable is assigning properly by doing console.log() but the problem comes when I try to use it in Vue.
app.blade.php
#if(Auth::user())
<script>
window.User = {!! json_encode(Auth::user()) !!}
console.log(window.User)
</script>
#endif
component.vue
<script>
export default {
data: function() {
return {
user: window.User
}
}
}
</script>
I've tried setting the data as window.User, this.User, and simply just User but it always comes up as undefined. What am I missing? Or is there any other/better way to do this?
Try the following Vue Component:
<template></template>
<script>
export default {
data: function() {
return {
user: window.User
}
},
created(){
console.log(this.user)
},
}
</script>
I could see the user data from the console.log in Vue component.

How to use Vue method as image source?

in Vue I am trying to use the result from a method as the source for an image:
HTML:
<img :src="getEnergyIcon(type)">
JS:
data() {
return {
energyTypeMap: new Map([
['colorless','#/assets/images/energy-icons/20px-Colorless-attack.png'],
['darkness','#/assets/images/energy-icons/20px-Darkness-attack.png'],
['dragon','#/assets/images/energy-icons/20px-Dragon-attack.png'],
['fairy','#/assets/images/energy-icons/20px-Fairy-attack.png'],
['fighting','#/assets/images/energy-icons/20px-Fighting-attack.png'],
['fire','#/assets/images/energy-icons/20px-Fire-attack.png'],
['grass','#/assets/images/energy-icons/20px-Grass-attack.png'],
['lightning','#/assets/images/energy-icons/20px-Lightning-attack.png'],
['metal','#/assets/images/energy-icons/20px-Metal-attack.png'],
['psychic','#/assets/images/energy-icons/20px-Psychic-attack.png'],
['water','#/assets/images/energy-icons/20px-Water-attack.png'],
])
}
},
And:
methods: {
getEnergyIcon(type){
return this.energyTypeMap.get(type.toLowerCase());
}
},
The method returns the correct path, but the image doesn't use that path as the source:
I want the result to be the same as the hardcoded result, but I want to achieve this by using the method, because I am going to use dynamic data that gives me one of the 11 types, I cannot use hardcoded paths.
I have been Googling around to find a solution but I can't find a solution that uses a direct method as a source for the image. How do I do this?
Thanks in advance.
Found this topic:
How to reference static assets within vue javascript
That mentioned the following:
In a Vue regular setup, /assets is not served.
The images become src="..." strings, instead.
And required me to use:
require();
Which I did like this:
data() {
return {
card: {},
energyTypeMap: new Map([
['colorless',require('#/assets/images/energy-icons/20px-Colorless-attack.png')],
['darkness',require('#/assets/images/energy-icons/20px-Darkness-attack.png')],
['dragon',require('#/assets/images/energy-icons/20px-Dragon-attack.png')],
['fairy',require('#/assets/images/energy-icons/20px-Fairy-attack.png')],
['fighting',require('#/assets/images/energy-icons/20px-Fighting-attack.png')],
['fire',require('#/assets/images/energy-icons/20px-Fire-attack.png')],
['grass',require('#/assets/images/energy-icons/20px-Grass-attack.png')],
['lightning',require('#/assets/images/energy-icons/20px-Lightning-attack.png')],
['metal',require('#/assets/images/energy-icons/20px-Metal-attack.png')],
['psychic',require('#/assets/images/energy-icons/20px-Psychic-attack.png')],
['water',require('#/assets/images/energy-icons/20px-Water-attack.png')],
])
}
},
It has solved my problem.

How can I put in a laravel route in a js file

I have my javascript code in a js file that I include in my main layout.
I want to call ajax, to a specific named route. Becuase it is a js file, the blade syntax can't be run from there.
I tried writing out the url, but the url changes depending on the route that is calling the ajax, so it's not pointing to the correct folder.
I'd rather use a names route.
Any other suggestions?
Have you considered writing out all the named routes you'll need into the view? Perhaps make a hash of routes and just make the ajax call to the one you need at the time. Something like:
var routes = {
'first': '{{ route('first') }}',
'second': '{{ route('second') }}',
// ....
};
// Somewhere later in code
$http.get(routes.second).then(function(result) {
// do something
});
In your view file, define a global JavaScript variable:
<script>
var globalRouteName = "{{ $route }}";
</script>
And now, in your js file, simply use globalRoutName as variable.

Resources