Laravel and Vue Pagination Fail - laravel

When I press the page 2 on pagination component, page=2 data comes to application and data never shows up on screen and pagination goes to 1 and everything is going to start point. I use bootstrap-vue for ui component library.
pagination component image:
Vue data variables:
isBusy: false,
output: {
message: "",
status: false
},
currentPage: 1,
tableData:{},
laravel api routes
Route::prefix('/pcustomers')->group( function() {
Route::post('/load', 'App\Http\Controllers\EmailListController#postPCustomer');
Route::middleware('auth:api')->post('/post', 'App\Http\Controllers\EmailListController#postPCustomer')->middleware(['web']);
Route::middleware('auth:api')->get('/all', 'App\Http\Controllers\EmailListController#allPCustomers')->middleware(['web']);
Route::middleware('auth:api')->get('/pcdata', 'App\Http\Controllers\EmailListController#pcData')->middleware(['web']);
Route::middleware('auth:api')->get('/delete', 'App\Http\Controllers\EmailListController#deletePCustomer')->middleware(['web']);
});
EmailListController function
public function pcData()
{
$pcData = DB::table('email_list')
->join('users', 'users.id', '=', 'email_list.workerId')
->select('email_list.*', 'users.username')
->paginate(100);
return response()->json($pcData);
}
Pagination component:
<b-pagination
v-model="currentPage"
:total-rows="tableData.total"
:per-page="tableData.to"
#input="getNewPageData()"
first-number
last-number
>
</b-pagination>
Here the axios post method for getting the data
getNewPageData(){
let list = this;
list.isBusy = true;
const page = list.currentPage;
axios.get("api/v1/pcustomers/pcdata?page="+page)
.then(function (response) {
list.tableData = response.data;
list.isBusy = false;
})
.catch(function (error) {
list.output = error;
});
},
It works at here for page 1
created(){
this.getNewPageData(this.currentPage);
}
Data Response for page 1:
{
"current_page":1,
"data":[
"..."
],
"first_page_url":"http:\/\/127.0.0.1:8000\/api\/v1\/pcustomers\/pcdata?page=1",
"from":1,
"last_page":4,
"last_page_url":"http:\/\/127.0.0.1:8000\/api\/v1\/pcustomers\/pcdata?page=4",
"links":[
{
"url":null,
"label":"Previous",
"active":false
},
{
"url":"http:\/\/127.0.0.1:8000\/api\/v1\/pcustomers\/pcdata?page=1",
"label":1,
"active":true
},
{
"url":"http:\/\/127.0.0.1:8000\/api\/v1\/pcustomers\/pcdata?page=2",
"label":2,
"active":false
},
{
"url":"http:\/\/127.0.0.1:8000\/api\/v1\/pcustomers\/pcdata?page=3",
"label":3,
"active":false
},
{
"url":"http:\/\/127.0.0.1:8000\/api\/v1\/pcustomers\/pcdata?page=4",
"label":4,
"active":false
},
{
"url":"http:\/\/127.0.0.1:8000\/api\/v1\/pcustomers\/pcdata?page=2",
"label":"Next",
"active":false
}
],
"next_page_url":"http:\/\/127.0.0.1:8000\/api\/v1\/pcustomers\/pcdata?page=2",
"path":"http:\/\/127.0.0.1:8000\/api\/v1\/pcustomers\/pcdata",
"per_page":100,
"prev_page_url":null,
"to":100,
"total":366
}

I did some changes on b-table and axios and it works now.
<b-table
id="pcustomers-table"
ref="pcustomers-table"
:busy="isBusy"
:items="tableData"
:fields="fields"
:per-page="resourceData.per_page"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc"
small
striped
hover
>
I removed :current-page="currentPage" here.
getPCustomersResourceData(){
let list = this;
list.isBusy = true;
const page = list.currentPage;
axios.get("api/v1/pcustomers/pcdata?page="+page)
.then(function (response) {
list.resourceData = response.data;
list.tableData = list.resourceData.data;
list.isBusy = false;
})
.catch(function (error) {
list.output = error;
});
},
I get the whole data and separate here like:
resourceData: {},
tableData:[],
Thanks to github.com/gilbitron and Kamlesh Paul.

Related

Vue 3 components not awaiting for state to be loaded

I am having some trouble using fetch in vuex to build state before rendering my page's components.
Here is the page component code:
async beforeCreate() {
await this.$store.dispatch('projects/getProjects');
},
And this is the state code it's dispatching:
async getProjects(context: any, parms: any) {
context.commit("loadingStatus", true, { root: true });
console.log("1");
await fetch(`${process.env.VUE_APP_API}/projects?`, {
method: "get",
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
})
.then((response) => {
console.log("2");
if (!response.ok) {
throw new Error(response.status.toString());
} else {
return response.json();
}
})
.catch((error) => {
// todo: tratamento de erros na UI
console.error("There was an error!", error);
})
.then((data) => {
context.commit("setProjects", { data });
console.log("3");
// sets the active project based on local storage
if (
localStorage.getItem(
`activeProjectId_${context.rootState.auth.operator.accountId}`
)
) {
console.log("setting project to storage");
context.dispatch("selectProject", {
projectId: localStorage.getItem(
`activeProjectId_${context.rootState.auth.operator.accountId}`
),
});
} else {
//or based on the first item in the list
console.log("setting project to default");
if (data.length > 0) {
context.dispatch("selectProject", {
projectId: data[0].id,
});
}
}
context.commit("loadingStatus", false, { root: true });
});
},
async selectProject(context: any, parms: any) {
console.log("4");
context.commit("loadingStatus", true, { root: true });
const pjt = context.state.projects.filter(
(project: any) => project.id === parms.projectId
);
if (pjt.length > 0) {
console.log("Project found");
await context.commit("setActiveProject", pjt[0]);
} else if (context.state.projects.length > 0) {
console.log("Project not found setting first on the list");
await context.commit("setActiveProject", context.state.projects[0]);
} else {
await context.commit("resetActiveProject");
}
await context.commit("loadingStatus", false, { root: true });
},
I've added this console.log (1, 2, 3, 4) to help me debug what's going on.
Right after console.logging "1", it starts to mount the components. And I only get logs 2, 3 and 4 after all components have been loaded.
How can I make it so that my components will only load after the whole process is done (i.e. after I log "4") ?
If your beforeCreate hook (or any client hooks) contains async code, Vue will NOT wait to it then render and mount the component.
The right choice here should be showing a loader when your data is fetching from the server. It will provide better UX:
<template>
<div v-if="!data"> Loading... </div>
<div v-else> Put all your logic with data here </div>
</template>
<script>
export default {
data() {
return {
data: null
}
},
async beforeCreate() {
this.data = await this.$store.dispatch('projects/getProjects');
},
}
</script>

Vuejs + Laravel: How To Count Records

Code for vue component:
data() {
return {
patrons : {},
}
},
methods: {
loadPatron(){
axios.get("api/patron")
.then(({data}) => (this.patrons= data.data));
//Count records
console.log(this.patrons.length); //This line of code does not seem to work.
},
}
How do we count the records and display them in the console.log?
You have to place console.log either inside axios get function after assignment
axios.get("api/patron")
.then(({data}) => {
this.patrons = data.data
console.log(this.patrons);
});
or create watcher for patrons property and console.log there
watch: {
patrons: {
handler: function() {
console.log(this.patrons)
},
deep: true
}
}

issue with slowly geting data from api to vue view

I have issue with very slowly getting data from laravel api to vue view, I did tutorial where I have:
import axios from 'axios';
const client = axios.create({
baseURL: '/api',
});
export default {
all(params) {
return client.get('users', params);
},
find(id) {
return client.get(`users/${id}`);
},
update(id, data) {
return client.put(`users/${id}`, data);
},
delete(id) {
return client.delete(`users/${id}`);
},
};
<script>
import api from "../api/users";
export default {
data() {
return {
message: null,
loaded: false,
saving: false,
user: {
id: null,
name: "",
email: ""
}
};
},
methods: {
onDelete() {
this.saving = true;
api.delete(this.user.id).then(response => {
this.message = "User Deleted";
setTimeout(() => this.$router.push({ name: "users.index" }), 1000);
});
},
onSubmit(event) {
this.saving = true;
api
.update(this.user.id, {
name: this.user.name,
email: this.user.email
})
.then(response => {
this.message = "User updated";
setTimeout(() => (this.message = null), 10000);
this.user = response.data.data;
})
.catch(error => {
console.log(error);
})
.then(_ => (this.saving = false));
}
},
created() {
api.find(this.$route.params.id).then(response => {
this.loaded = true;
this.user = response.data.data;
});
}
};
</script>
It's load data from api very slowly I see firstly empty inputs in view and after some short time I see data, if I open api data from laravel I see data immediately, so my question is How speed up it? Or maby I did something wrong?
Whenever I am using an API with Vue, I usually make most of my API calls before opening the Vue then passing it in like this.
<vue-component :user="'{!! $user_data !!}'"></vue-component>
But if you have to do it in the Vue component, I am not sure if this will show improvement over your method but I would set it up with the "mounted" like so.
export default {
mounted() {
api.find(this.$route.params.id).then(response => {
this.loaded = true;
this.user = response.data.data;
});
}
}
Also heres a good tutorial on Axios and how to use HTTP Requets with Vue.
Hopefully this answered your question, good luck!

Sort() not working

I'm having an issue with the sort() in ranking data from coinmarketcap api. With an ajax api call, sort works in returning an array with the right ranking. With an axios api call, seen below, it doesn't.
Here is my code using axios and vue.js:
let coinMarket = 'https://api.coinmarketcap.com/v2/ticker/?limit=10'
let updateInterval = 60 * 1000;
let newApp = new Vue({
el: '#coinApp',
data: {
// data within an array
results: []
},
methods: {
getCoins: function() {
axios
.get(coinMarket)
.then((resp) => {
this.results = formatCoins(resp);
});
},
getColor: (num) => {
return num > 0 ? "color:green;" : "color:red;";
},
},
created: function() {
this.getCoins();
}
})
setInterval(() => {
newApp.getCoins();
},
updateInterval
);
function formatCoins(res) {
var coinDataArray = []
Object.keys(res.data).forEach(function(key) {
coinDataArray.push(res.data[key])
})
coinDataArray.sort(function(a,b) {
return a.rank > b.rank
})
console.log(coinDataArray)
}
Where am I going wrong?
If you look into the data responded by https://api.coinmarketcap.com/v2/ticker/?limit=10, you will find the data you need is under res.data.data, not res.data.
So within the function=formatCoins, replace res.data with res.data.data, then works.
Vue.config.productionTip = false
let coinMarket = 'https://api.coinmarketcap.com/v2/ticker/?limit=10'
let updateInterval = 60 * 1000;
function formatCoins(res) {
var coinDataArray = []
Object.keys(res.data.data).forEach(function(key) {
coinDataArray.push(res.data.data[key])
})
coinDataArray.sort(function(a,b) {
return a.rank - b.rank
})
return coinDataArray
}
let newApp = new Vue({
el: '#coinApp',
data: {
// data within an array
results: []
},
methods: {
getCoins: function() {
axios
.get(coinMarket)
.then((resp) => {
this.results = formatCoins(resp);
});
},
getColor: (num) => {
return num > 0 ? "color:green;" : "color:red;";
},
},
created: function() {
this.getCoins();
}
})
setInterval(() => {
newApp.getCoins();
},
updateInterval
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>
<script src="https://unpkg.com/vue#2.5.16/dist/vue.js"></script>
<div id="coinApp">
<div v-for="(record, index) in results" :key="index">
{{index}} - {{record.name}}: {{record.rank}}
</div>
</div>

Can't invoke the component's method

Using an EventBus on my Laravel-Vuejs project. I'm emitting an items-updated event from ItemCreate component after the successful Item creation. On the same page I'm using ItemList component which shows a list of created Items
Here is the codes:
app.js file
require('./bootstrap');
window.Vue = require('vue');
window.EventBus = new Vue();
Vue.component('item-list',
require('./components/entities/item/ItemList'));
Vue.component('item-create',
require('./components/entities/item/ItemCreate'));
const app = new Vue({
el: '#app'
});
ItemCreate.vue Component
export default {
data: function () {
return {
itemName: ''
}
},
methods: {sendItemData: function () {
axios.post('/dashboard/item', {
name: this.itemName
})
.then(response => {
if (response.status === 201) {
toastr.success('Item created successfully!', {timeout: 2000});
EventBus.$emit('items-updated');
}
})
.catch(error => {
toastr.error(error, 'Ooops! Something went wrong!');
})
}
}
}
ItemList.vue Component
export default {
data: function () {
return {
items: [],
}
},
methods: {
getItems: function () {
axios.get('/dashboard/items')
.then(response => {
this.items = response.data;
})
.catch(error => {
toastr.error(error, 'Ooops! Something went wrong!');
})
}
},
mounted() {
this.getItems();
EventBus.$on('items-updated', function () {
this.getItems();
});
}
}
It was a general JS mistake. Working code:
on ItemList.vue Component
export default {
data: function () {
return {
items: [],
}
},
methods: {
getItems: function () {
axios.get('/dashboard/items')
.then(response => {
this.items = response.data;
})
.catch(error => {
toastr.error(error, 'Ooops! Something went wrong!');
})
}
},
mounted() {
this.getItems();
let vm = this;
EventBus.$on('items-updated', function () {
vm.getItems();
});
}
}

Resources