How can I preload data for vue.js in Laravel Spark? - laravel

According to the docs and examples, I have perfectly working code that functions great:
Vue.component('admin-competitions-index', {
data: function() {
return {
competitions: []
}
},
mounted() {
this.$http.get('/api/admin/competitions')
.then(response => {
this.competitions = response.data;
});
},
methods: {
/**
* Toggle whether a competition is published or not.
*/
togglePublished(competition) {
Spark.patch(`/api/admin/competitions/togglePublished/${competition.id}`, this.togglePublishedForm)
.then(response => {
competition.is_published = response;
});
}
}
});
However, I'd like to change this code to save the extra request that is made on page load. I don't see a convention anywhere in Laravel or Spark where this is done. I'm guessing that all I need to do is set a JS variable but I'm not sure where it would be proper to do so.
I also understand that this kind of defeats the point of using vue for asynchronous loading, but nevertheless I would like to learn this. I think it will become more useful if I were to use vue for my #show restful requests where even if I wanted everything to load asynchronously I would at the very least have to supply vue with the competition ID that I want loaded.

This works out of the box:
#section('scripts')
<script>
var competition = {!! $competition !!};
</script>
#endsection

Related

Laravel vue.js 2 response view won't output parameters

I am new to vue.js and recently been assigned a project to learn it and refactor old code to vue.js like some of the existing pages already have been and I am having some issues. vue2
My question:
I have a get request with a controller that has a response something like this:
return Response::view('somebladefile', ['title' => 'some_title']);
Within the blade file I include a js file which will be responsible for vue
<script src="{{ cdnMix('somefile.js') }}"></script>
somefile.js contents:
const IndexPage = Vue.component('indexpage',require('./somepath/IndexPage.vue').default);
window.indexPageInstance = new IndexPage().$mount('#vuecontainerid');
So now within IndexPage.vue i would like to access variable 'title' that I passed with the response to my blade file originally. What would be the best way one would go about it? Tried few ways I found on YT/Google but without success, this is my code currently, any pointers would be appreciated, thanks!
<template>
<HeaderComponent></HeaderComponent>
</template>
<script>
const HeaderComponent = require('./somepath/HeaderComponent.vue').default;
export default {
name: 'indexpage',
props: ['data'],
components: {
'HeaderComponent': HeaderComponent,
},
data: function() {
return {
// why doesn't it work!!: '',
}
},
mounted: function() {
console.log(this.data);
}
}
</script>
Vue works, but I can't seem to be able to access 'title' variable.
Also I would like to be able to access 'title' within other components like the HeaderComponent I have within indexpage

vue 2 v-for not working after loading json with axios

I searched the internet for a solution but none did work so far.
I am having a Vue component where I want to load dropdown content afterwards. Since it does not work, I simplified the code such that it should only show me the elements (which are driver names).
The problem is, that the v-for seems not to work, as the elements are not created in the DOM.
Here goes the code:
<template>
<div class="list-group">
<a class="list-group-item" v-for="driver in drivers">
{{driver.name}}
</a>
</div>
</template>
<script>
export default {
name: "DriverComponent",
data: function (){
return {
drivers: [],
}
},
mounted(){
this.loadDrivers();
console.log(this.drivers);
},
methods: {
loadDrivers: function(){
axios.get('/api/drivers')
.then(
(response) => {
this.drivers = response.data.data;
console.log(this.drivers);
}
)
.catch(function(error){
console.log(error);
});
// console.log(this.drivers);
}
}
}
</script>
In my app.js:
require('./bootstrap');
window.Vue = require('vue').default;
Vue.component('driver-component', require('./components/DriverComponent.vue').default);
const drivers = new Vue({
el: '#driv',
});
And my html looks as follows:
<div id="driv">
<driver-component></driver-component>
</div>
As you can see, I added some logs, which look like this:
Image of console output
Interestingly, it should be the same array, but the first array is empty but the second has the right values in it.-> EDIT: clarified, thank you
to highlight the problem: i would expect a list like:
v-for created list
Instead, I get a blank page.
It works, if I initialize the drivers array with the data I get in json. However, since I load the data afterwards, it seems not to work
Thank you for your help!
BR
Johannes
EDIT:
I am using "axios": "^0.21" and the controller is:
public function index(){
return DriverResource::collection(Drivers::all());
}
this controller returns the array in a data field, therefore, I set the response.data.data (meaning two times data)
The backend returns:
{"data":[{"id":1,"name":"UPS"},{"id":2,"name":"Hermes"}]}
See the homepage for axios. Under the "Response Schema" section they provide what a response looks like. Specifically for data, it's
{
// `data` is the response that was provided by the server
data: {}
< ... omitted for brevity ... >
}
Please check again what your backend is returning or is supposed to return. Log the whole response you get.
The this.drivers = response.data.data; seems to be incorrect, however the this.drivers = response.data; should work.
You didn't say which version of axios you are using or show your configuration so I'm using the following for an example:
axios = ^0.21.1
vue-axios = ^3.2.4
Replaced "name" with "title" to match the response format below:
{
"title": "delectus aut autem",
< ... omitted for brevity ... >
},
--
loadDrivers: function(){
Vue.axios.get('https://jsonplaceholder.typicode.com/todos')
.then(
(response) => {
this.drivers = response.data; // <<-- works and many task titles are shown on page
// this.drivers = response.data.data; // <<-- DOES NOT WORK LIKE FOR YOU, blank page
console.log(this.drivers);
}
)
.catch(function(error){
console.log(error);
});
// console.log(this.drivers);
}

How to pass simple user input from Vue to Laravel Controller?

I'm trying to create something simple with Laravel + Vue.js without having to use the database.
I have two inputs from a Vue Component, and I was wondering how I pass those two values back into a Controller.
Usually, you use Axios to complete CRUD functions, but I honestly just want to pass simple values to the backend, and then have the backend transfer an array into back to the Vue Component.
Any advice? All the decent tutorials online usually use a database to transfer data back and forth.
Have you heard of inertiajs?
inertiajs allows you to create fully client-side rendered, single-page apps, without much of the complexity that comes with modern SPAs. It does this by leveraging existing server-side frameworks.
I was able to send data back and forth using axios
Here is what I had for my Vue Component:
<template> ... </template>
<script>
export default {
data() {
return {
name: '',
days: ''
}
},
methods: {
getData() {
axios.get('/api/urihere', {
params: {
name: this.name,
days: this.days
}
}).then((response) => {
console.log(response.data)
}).catch((error) => {
console.log(error)
})
}
},
mounted() {
//
}
}
</script>
While I had you had a simple get for Routes
Route::get('/urihere', [UrihereController::class, 'someMethod']);
and inside the said-controller
public function someMethod(Request $request)
{
return [$request->name, $request->days];
}

When i set axios response in vue js i get an empty array in laravel blade

I am trying to display results in my page, When i log response. I can see the response, I have tried passing the response to vue js data, but each time it displays an empty array
var app = new Vue({
el: '#app',
data: {
results: []
},
mounted(){
var url = "{{ url('fetch/messages') }}";
axios.get(url)
.then(function (response) {
console.log(response.data);
this.results = response.data;
})
.catch(function (error) {
console.log(error);
});
}
I am trying to display the response in the page #{{ results }}
The reason your data is not getting added to the Vue instance is because this will not refer to the Vue instance inside a closure (traditional function () {}). Please have a look at this article for more information on scope and this keyword in javascript.
Below I refer to ES quite a bit which stands for ECMAScript. Here is an article to show the difference between it and vanilla javascript.
I can see from your post that you're using ES6/ES2015 syntax for your method definitions so I'm assuming you're happy with just using modern browsers for now.
If this is the case then you can use Arrow Functions to get past the scope issue:
.then(response => {
console.log(response.data);
this.results = response.data;
})
If not, then as mentioned in the scope article above, you would need to assign this to a variable:
var self = this;
axios.get(url)
.then(function (response) {
console.log(response.data);
self.results = response.data;
});
If this is the case, then I would also suggest not using the ES6 method definitions either so change mounted(){ to mounted: function () {.
Finally, if you want to be able to use modern/new javascript e.g. ES6/ES2015 and above, but have your code work consistently with older browsers then I would suggest using something like Laravel mix to compile your javascript for you.
Laravel Mix Documentation
Laravel Mix tutorial series
You cannot have the following line of code, it will break.
var url = "{{ url('fetch/messages') }}";

Updating vuejs component with ajax call from the parent

New to VueJs. I'm wondering how/where would I make an Ajax call to pull data dynamically down to populate the following Vue table?
https://jsfiddle.net/yyx990803/xkkbfL3L/?utm_source=website&utm_medium=embed&utm_campaign=xkkbfL3L
I've (roughly) modified the example above as follows:
var demo = new Vue({
el: '#demo',
data: {
searchQuery: '',
gridColumns: ['name', 'power'],
gridData: []
},
methods: {
fetchUsers: function() {
...
// ajax call using axiom, fetches data into gridData like this:
axios.get('http://localhost/url')
.then(function(response) {
this.gridData = response.data;
})
.catch(function(error) { console.log("error"); })
...
}
},
created: function() {
this.fetchUsers();
}
})
I'm trying to incorporate the ajax pieces from here:
https://jsfiddle.net/chrisvfritz/aomd3y9n/
I've added the fetchUser method which makes the ajax call to pull the data down. I'm able to pull down my data and print it to the console using both fetch and axiom, so I know that part works.
However, my data never appears or updates. The table loads blank. I think it has something to do with me putting the method and created hook on the Vue model object (demo), rather than on the component itself. But I'm not quite sure how to modify the example to resolve it, as the example passes the data in from the parent.
Can someone give me some guidance?
You problem is right over here:
.then(function(response) {
this.gridData = response.data;
})
Within your anonymous function within your then you don't have the context you expect. The most simple solution is adding a .bind(this) to the method.
.then(function(response) {
this.gridData = response.data;
}.bind(this))
By adding it your method body will be aware of the outer context and you can access your components data.

Resources