using axios data from Laravel pagination array - laravel

ok I am stumped and I know its going to be something stupid. So let me explain more in detail. The code above is what I believe should work for pagination from a Laravel controller to a vue component. I get that I am not fully accounting for pagination and I can handle that later but the first results are not available for use when I do this and I do not understand where my syntax is wrong.
Vue:
<ul role="list" class="space-y-4">
<li
v-for="item in allActivities"
:key="item.id"
class="bg-gray-800 px-4 py-6 shadow sm:p-6 sm:rounded-lg"
>
{{ item.description }}
</li>
</ul>
Mounted:
mounted() {
axios
.get("/activity")
.then((response) => (this.allActivities = response.data));
},
Controller
public function index()
{
$activity = Activity::paginate(10);
return $activity;
}
If in the v-if I change it to allActivities.data it refreshes to show the data until I reload the page and get id not found.
If I change the axios to response.data.data it works, but I lose pagination.
IM stuck

response.data is the result from laravel
response.data.data if the data key in the result which is a list of your models
response.data will contain these keys if using
current_page
data
first_page_url
from
last_page
last_page_url
links
next_page_url
path
per_page
prev_page_url
to
total

I did not fully understand the problem. If you want to change page, send the value of the page you want to display to the fetchActivities() method.
EDIT!
<script>
export default {
data() {
return {
allActivities: {
data: [],
total: null
}
}
},
methods: {
async fetchActivities(page = 1){
const {data:activities} = await axios.get(`/activity?page=${page}`)
this.allActivities.data.push(activities.data)
this.allActivities.total = activities.total
}
},
created() {
this.fetchActivities()
}
}
</script>
<template>
<div v-if="allActivities.data.length > 0">
<ul role="list" class="space-y-4">
<li
v-for="(item, index) in allActivities.data"
:key="index"
class="bg-gray-800 px-4 py-6 shadow sm:p-6 sm:rounded-lg"
>
{{ item.description }}
</li>
</ul>
</div>
</template>

Related

Inertia mounted hook with search resets pagination on every action

My vue file:
data() {
return {
search: '',
}
},
mounted() {
this.search = this.filters.search ?? '';
},
watch: {
search(value) {
Inertia.get('/contacts', { search: value }, {
preserveState: true,
replace: true,
})
}
The Laravel Controller:
$contacts = Model::query()
->paginate(10)
->withQueryString();
return Inertia::render('Contacts/List', [
'contacts' => $contacts,
'filters' => request()->only(['search']),
'currentPage' => request()->page,
]);
It all works perfectly if the mounted block is missing.
With it, on every Inertia reload a "new search" is registered (since it's changed in the mounted hook) and it returns to page 1, so basically, every time you change the page it returns you to page 1.
It should be working perfectly with the Composition API's setup, but not sure why can't I get it to work here.
I use axios instead of Inertia.js in pagination
<template>
<div class="row mt-4">
<div class="col-md-5">
<span
>showing {{ data.from }}-{{ data.to }} of
{{ data.total }} items</span
>
</div>
<div class="col-lg-7">
<nav aria-label="...">
<ul class="pagination float-end">
<template v-for="link in data.links" :key="link.id">
<li v-if="!link.url" class="page-item">
<a #click.prevent="paginate(link.label)" class="page-link">
<span
aria-hidden="true"
v-html="link.label"
></span>
</a>
</li>
<li
v-else
:class="{ active: link.active }"
class="page-item"
>
<a
#click.prevent="paginate(link.label)"
v-html="link.label"
class="page-link"
></a>
</li>
</template>
</ul>
</nav>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
props: ["data", "url"],
methods: {
paginate(label) {
console.log(`${route(this.url)}?page=${label}`);
axios.get(`${route(this.url)}?page=${label}`).then((res) => {
this.$emit('paginate', res.data)
});
}
}
}
</script>
I ran into the same issue, and after some digging I found this answer. The gist is that you should set your search parameter directly in the data attribute instead of using mounted():
data() {
return {
search: this.filters.search ?? '',
}
},
watch: {
search(value) {
Inertia.get('/contacts', { search: value }, {
preserveState: true,
replace: true,
})
}

Difficult to get associate table's record in Vuejs from Laravel collection

I'm using Vuejs and Laravel building a live feed app, but i found that it is difficult to get associate data from collection in Vuejs, is there anyway to get those data easily?
Here is my attempt:
<div class="sl-item" v-for="post, index in posts">
<a href="javascript:void(0)">
<div class="sl-content">
{{post}}
<br>
------------------------
<br>
{{getUser(post.user_id)}}
</div>
</a>
</div>
Here is my methods that i intend to retrieve user record:
methods: {
getUser (id)
{
return axios.get("/user/getUser/" + id)
.then(response => {
console.log(response.data);
return response.data;
});
}
},
But this is what i got:
I can log what i get in console, but i can't display or access the thing i return from my method.
Is there any other easier way to achieve this?
You fetching all the data from collection. that's why you also getting unwanted data in your object
in your current situation (without changing in your controller script) you can access those data as like:
public function index(Request $request)
{
if ($request->ajax()) {
return Post::with(['user' => function($query){
$query->select(['id', 'name'])
}])
->select(['id', 'title', 'description'])
->get;
}
}
if you do this in your controller, then in your vue file,
data:function(){
return{
posts: [],
};
},
methods: {
getPosts ()
{
return axios.get("/posts")
.then(response => {
this.posts = response.data;
});
}
},
and in component:
<div class="sl-item" v-for="post, index in posts">
<a href="javascript:void(0)">
<div class="sl-content">
{{post.title}}
<br>
------------------------
<br>
{{ post.user.name }}
</div>
</a>
</div>

Laravel router-link works only the first time

I am trying to fetch results from database in News.vue, and display them in Topnews.vue. I have two links fetched. When I click link1, it shows up the Topnews.vue template with everything working as intended, however, if i click link2, nothing happens, except for that the URL changes, but the template does not show up the result. If i refresh the page and click link2 or click on the navbar, then link2, it shows up, and same, clicking then link1, changes the URL, but doesnt show up. I'm really stuck on that and I'd be really glad if you help me out on that issue. Hope you understand.
News.vue
<template id="news">
<div class="col-sm-5">
<div class="cars" v-for="row in filteredNews" >
<div class="name" >
<p class="desc_top_time">{{row.created_at}}</p>
<span class="last_p"> {{row.category}}</span>
<h3 style="margin-bottom:-4px; font-size: 16px;">
<router-link class="btn btn-primary" v-bind:to="{name: 'Topnews', params: {id: row.id} }">{{row.title}}</router-link></h3>
</div></div></div>
</template>
<script>
export default {
data: function() {
return {
news: [],
}
},
created: function() {
let uri = '/news';
Axios.get(uri).then((response) => {
this.news = response.data;
});
},
computed: {
filteredNews: function() {
if (this.news.length) {
return this.news;
}
}
}
}
</script>
Topnews.vue
<template id="topnews1">
<div class="col-sm-7">
<div class="cars">
<img :src="topnews.thumb" class="img-responsive" width=100%/>
<div class="name" ><h3>{{ topnews.title }}</h3>
<p>
<br>{{ topnews.info }}<br/>
</p>
</div></div></div>
</template>
<script>
export default {
data:function(){
return {topnews: {title: '', thumb: '', info: ''}}
},
created:function() {
let uri = '/news/'+this.$route.params.id;
Axios.get(uri).then((response) => {
this.topnews = response.data;
});
}
}
</script>
Like GoogleMac said Vue will reuse the same component whenever possible. Since the route for both IDs use the same component Vue will not recreate it, so the created() method is only being called on the first page. You'll need to use the routers beforeRouteUpdate to capture the route change and update the data.
in TopNews.vue:
export default {
data:function(){
return {topnews: {title: '', thumb: '', info: ''}}
},
beforeRouteEnter:function(to, from, next) {
let uri = '/news/'+ to.params.id;
Axios.get(uri).then((response) => {
next(vm => {
vm.setData(response.data)
})
});
},
beforeRouteUpdate: function(to, from, next) {
let uri = '/news/'+ to.params.id;
Axios.get(uri).then((response) => {
this.setData(response.data);
next();
});
},
methods: {
setData(data) {
this.topnews = data
}
}
}
If you click a link referring to the page you are on, nothing will change. Vue Router is smart enough to not make any changes.
My guess is that the IDs are messed up. If you are using Vue devtools you will be able to easily see what data is in each link. Are they as you expect.

VueJs component: can't attribute axios reponse to a component variable

I am new to VueJs with Laravel. I have a component called Event in which a 'read more...' link shoud trigger a function that fetch the event infos from the data base and store the in a variable withing this same component.
Here is the code for my component:
<template>
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">
<h5>
Title: {{ event.event_name }}
<span class="pull-right">
#click=getEventInfo(event.id)>Read more ...</a></span>
</h5>
<h5>publised by: {{ event.user.name }}
<span class="pull-right" v-text="timeFromNow(event.created_at)"></span>
</h5>
</div>
<div class="panel-body">
<p>{{ event.event_detail }}</p>
</div>
<div class="panel-footer">
<p>
<span>Event for: {{ event.event_to_whom }}</span>
<span>When: {{ dayOfDate(event.event_when_date) }} {{ event.event_when_date }} at {{event.event_when_time}}</span>
</p>
</div>
</div>
</div>
</template>
<script>
import moment from 'moment';
export default {
name: 'app-event',
props:['event'],
data() {
return {
eventInfo: {}
}
},
methods: {
timeFromNow(tmp) {
return moment(tmp).fromNow();
},
dayOfDate(d) {
let dt = moment(d, "YYYY-MM-DD");
return dt.format('dddd');
},
//event.id
getEventInfo(id){
let url = 'events/' + id;
axios.get(url)
.then((response) => {
console.log(response.data); //returns data
this.eventInfo = response.data;
console.log(this.eventInfo);//returns data
});
console.log(this.eventInfo); //returns nothing
}
}
}
</script>
The problem is when I click the 'read more...' link axios returns a response that I can check using console.log(response.data). Hovever when I console.log(this.eventInfo) outside the axios closure, it returns and ampty object.
Am I doing something wrong? Sorry if the question is too basic.
Thanks
L.B
You are printing logging the property before it is assigned a value.
The code below should resolve any errors
import moment from 'moment';
export default {
name: 'app-event',
props:['event'],
data() {
return {
eventInfo: {}
}
},
methods: {
timeFromNow(tmp) {
return moment(tmp).fromNow();
},
dayOfDate(d) {
let dt = moment(d, "YYYY-MM-DD");
return dt.format('dddd');
},
//event.id
getEventInfo(id){
let url = 'events/' + id;
axios.get(url)
.then((response) => this.handleResponse(response.data));
},
handleResponse(eventInfo) {
console.log(eventInfo);
// do something with the eventInfo...
}
}
Your axios call is asynchrone so your outside console.log will be process before the return of the response.
Just keep your code in the .then((response) => { // here i proceed the read more }

go to a laravel controller using vue js's data

This is my vue
new Vue({
el: '#notificationMenu',
data: {
showModal: false,
patients: [],
duepatients: []
},
created: function(){
this.getPatients();
this.addUsers();
},
methods: {
getPatients: function(){
$.getJSON("{{route('api_patients')}}", function(patients){
this.patients = patients;
}.bind(this));
setTimeout(this.getPatients, 1000);
},
addUsers: function(){
this.$http.get('/govaccine/addUsers', '').then((response) => {
}, (response) => {
this.formErrors = response.data;
});
setTimeout(this.addUsers, 10000);
},sendSMS: function(val){
$.getJSON('sendsms/' + val,function(duepatient){
this.duepatients = duepatient;
}.bind(this));
}
}
});
and this is my html
<ul class="notifications-list" v-for="patient in patients">
<li class="item no-data">You don't have notifications</li>
<!-- use the modal component, pass in the prop -->
<modal v-if="showModal" #close="showModal = false">
<!--
you can use custom content here to overwrite
default content
-->
<h3 slot="header">custom header</h3>
</modal>
<a v-on:click="sendSMS(patient.due_date)">
<li class="item js-item " data-id="5" >
<div class="details">
<strong>#{{ patient.total}} patients</strong> are due for immunization on #{{patient.due_date}}
<span class="date">{{-- #{{patient.created_at}} --}}</span>
</div>
<button type="button" class="button-default button-dismiss js-dismiss">×</button>
</li>
</a>
</ul>
If I loop through vue js data using v-for how do i pass the data each loop in {{route('patient.show', parameter)}} so i can put a parameter on it.
or is there anyway to go to the controller and go to the other page?
yes you should use router-link. complete example here.
if I got you question wrong just tell me.

Resources