This question is very similar to This question
I have set up a Vue page with Laravel and showing all posts with a help of a GET request. I am also listening to a Laravel ECHO event and unshifting the value to the all posts array making it appear on top.
I have set up the infinite scroll and paginating 5 results per page using this package. Results appear on the page and pushing to the array from the listener also works. However, when infinite scroll loads the 2nd results page, the 6th result is duplicated.
The aforementioned package accepts next_cursor an offset value as the parameter instead of page=2 so it exactly loads the value without any duplications.
Controller.php
public function pusherGet(Request $request) {
$jobs = Job::orderBy('id','desc')->cursorPaginate();
return response()->json($jobs);
}
Vue file
<template>
<div>
<h3 class="text-center">All Jobs</h3><br/>
<div class="container">
<div class="card" v-for="(job,index) in jobs" :key="index">
<div class="card-body">
<h4 class="card-title">{{ job.id }}</h4>
<p class="card-text">{{ job.request_type}}</p>
</div>
</div>
</div>
<infinite-loading #infinite="getJob"></infinite-loading>
</div>
</template>
<script>
export default {
data() {
return {
page:1,
jobs: [],
}
},
mounted() {
this.listenNewJobs();
},
created() {
},
methods: {
listenNewJobs() {
Echo.channel('chat-room.1')
.listen('JobCreated', (e) => {
console.log(e);
this.jobs.unshift(e.job);
});
},
getJob($state) {
axios.get('getjobs', {
params: {
page: this.page,
},
}).then(({data})=> {
console.log(data)
if(data.data.length) {
this.page += 1;
this.jobs.push(...data.data)
$state.loaded();
} else {
$state.complete();
}
});
}
}
}
</script>
Results Json
{
data: Array(5), path: "getjobs?page=1", previous_cursor: "100", next_cursor: "96", per_page: 5, …}
data: (5) [{…}, {…}, {…}, {…}, {…}]
next_cursor: "96" // this is the parameter which i should attach to the GET request to paginate correct results
next_page_url: "getjobs?page=1&next_cursor=96"
path: "getjobs?page=1"
per_page: 5
prev_page_url: "getjobs?page=1&previous_cursor=100"
previous_cursor: "100"
__proto__: Object
Any help would be greatly appreciated.
Edit : How to Set the URL for the GET request to paginate the results from the GET request response for paginated results to avoid 2nd page result duplication ?
Try the following:
<script>
export default {
data() {
return {
jobs: [],
isInitialLoaded: false,
currentPage: 1,
lastPage: 0,
}
},
mounted() {
this.listenNewJobs();
},
created() {
//
},
methods: {
listenNewJobs() {
Echo.channel('chat-room.1')
.listen('JobCreated', (e) => {
console.log(e);
this.jobs.unshift(e.job);
});
},
async getJob($state){
await this.fetchData().then((response) => {
this.lastPage = response.data.last_page;
if (response.data.data.length > 0) {
response.data.data.forEach((item) => {
const exists = this.jobs.find((job) => job.id == item.id);
if (!exists) {
// this.jobs.unshift(item); // Add to front of array
this.jobs.push(item);
}
});
if (this.currentPage - 1 === this.lastPage) {
this.currentPage = 2;
$state.complete();
} else {
this.currentPage += 1;
}
$state.loaded();
} else {
this.currentPage = 2;
$state.complete();
}
});
this.isInitialLoaded = true;
},
fetchData() {
const url = this.isInitialLoaded ? `/getjobs?page=${this.currentPage}` : `/getjobs`;
return axios.get(url);
},
}
}
</script>
Related
I want to display a chart with money donated and the date of the donation. Mysteriously, the chart shows up sometimes (~5% of the time), yet doesn't the other 95% of the time (See pictures at bottom).
I'm very confused about this issue I'm having. I want to create a line chart using some data I'm getting from an API. I'm using chart.js. Sometimes it shows up and sometimes it doesn't. It has nothing to do with getting the API data as (from looking at the console) that is done immediately. So I am sure it is a problem with my way of using Chart.js.
Here is my LineChart.vue:
<script>
import { Line } from 'vue-chartjs'
export default {
name: 'LineChart',
extends: Line,
props: {
label: {
type: String
},
chartData: {
type: Array
},
options: {
type: Object
}
},
mounted () {
const dates = this.chartData.map(d => d.donationDate).reverse()
const totals = this.chartData.map(d => d.totalMoney).reverse()
this.renderChart({
labels: dates,
datasets: [{
label: this.label,
data: totals
}]
},
this.options)
}
}
</script>
Here is my code for Fundraiser.vue:
<template>
<div class="container">
<div class="row mt-5">
<div class="col">
<h2>Positive</h2>
<line-chart :chart-data=recentDonations :options=chartOptions label='Positive'>
</line-chart>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
import moment from 'moment'
import LineChart from '../components/LineChart.vue'
export default {
name: 'Fundraiser',
components: { LineChart },
data () {
return {
recentDonations: [],
chartOptions: {
responsive: true,
maintainAspectRatio: false
}
}
},
async created () {
const { data } = await axios({
url: 'http://api.justgiving.com/[MY API KEY]/v1/crowdfunding/pages/[SOME-PAGE]/pledges',
method: 'get',
headers: {
Accept: 'application/json'
}
})
console.log(data)
data.pledges.forEach(d => { // this part works fine.
if (d.donationAmount != null) {
const dateInEpochFormat = d.activityDate.substring(6, 16)
const donationMade = moment.unix(dateInEpochFormat).format('MM/DD')
this.recentDonations.push({ donationDate: donationMade, totalMoney: d.donationAmount })
}
console.log(this.recentDonations)
})
}
}
</script>
As you can see from the pictue below, the data is being pulled fine (array of objects with two properties: donateDate and totalMoney)
So sometimes it shows up (very very rarely):
[][
Then I refresh the page (without touching ANY code) and all of a sudden:
Can someone please help me solve this mystery?
Try to render the graph after receiving the response from the http request, maybe with an if statement and a variable as flag:
<template>
<div class="container">
<div class="row mt-5">
<div class="col" v-if="show">
<h2>Positive</h2>
<line-chart
:chart-data="recentDonations"
:options="chartOptions"
label="Positive"
>
</line-chart>
</div>
</div>
</div>
</template>
In your export default object, you can have this:
export default {
name: 'Fundraiser',
components: { LineChart },
data () {
return {
show: false,
recentDonations: [],
chartOptions: {
responsive: true,
maintainAspectRatio: false
}
}
},
async created () {
const { data } = await axios({
url: 'http://api.justgiving.com/[MY API KEY]/v1/crowdfunding/pages/[SOME-
PAGE]/pledges',
method: 'get',
headers: {
Accept: 'application/json'
}
})
console.log(data)
data.pledges.forEach(d => { // this part works fine.
if (d.donationAmount != null) {
const dateInEpochFormat = d.activityDate.substring(6, 16)
const donationMade = moment.unix(dateInEpochFormat).format('MM/DD')
this.recentDonations.push({ donationDate: donationMade, totalMoney:
d.donationAmount })
}
console.log(this.recentDonations)
})
this.show = true;
}
}
This is a workaround, You are waiting to have the data before render the graph, than way the first time that the graph is rendered, it can use the data and show the information.
The reason to not see data in the graph is because when the graph is rendered there is not information to show, once you get the response from the http request the graph is not updated, to do so, you must to watch the chartData prop, and once chartData is updated, you must call the chart.js update graph method (you can read more about it here: https://www.chartjs.org/docs/latest/developers/updates.html)
A better way to handle the data update is to assign the value to this.recentDonations after the forEach, that way you are not getting updates every time a pledge is pushed:
...
const donations = [];
data.pledges.forEach(d => { // this part works fine.
if (d.donationAmount != null) {
const dateInEpochFormat = d.activityDate.substring(6, 16)
const donationMade = moment.unix(dateInEpochFormat).format('MM/DD')
donations.push({ donationDate: donationMade, totalMoney:
d.donationAmount })
}
console.log(this.recentDonations)
})
this.recentDonation = donations;
this.show = true;
...
I did a test with a timeout function using this code (I don't know how to use the justgiving api):
<template>
<div class="container">
<div class="row mt-5">
<div class="col" v-if="show">
<h2>Positive</h2>
<line-chart
:chart-data="recentDonations"
:options="chartOptions"
label="Positive"
>
</line-chart>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
import moment from "moment";
import LineChart from "../components/LineChart.vue";
export default {
name: "Fundraiser",
components: { LineChart },
data() {
return {
show: false,
recentDonations: [],
chartOptions: {
responsive: true,
maintainAspectRatio: false
}
};
},
methods: {
request() {
const pledges = [
{ donationDate: "11/08", donationAmount: 5 },
{ donationDate: "11/09", donationAmount: 5 },
{ donationDate: "11/10", donationAmount: 5 },
{ donationDate: "11/11", donationAmount: 5 },
{ donationDate: "11/12", donationAmount: 5 },
{ donationDate: "11/13", donationAmount: 5 },
{ donationDate: "11/14", donationAmount: 5 },
{ donationDate: "11/15", donationAmount: 5 },
{ donationDate: "11/16", donationAmount: 5 },
{ donationDate: "11/17", donationAmount: 5 },
{ donationDate: "11/18", donationAmount: 5 },
{ donationDate: "11/19", donationAmount: 5 },
{ donationDate: "11/20", donationAmount: 5 },
{ donationDate: "11/21", donationAmount: 5 },
{ donationDate: "11/22", donationAmount: 5 }
];
pledges.forEach(d => {
// this part works fine.
// if (d.donationAmount != null) {
// const dateInEpochFormat = d.activityDate.substring(6, 16);
// const donationMade = moment.unix(dateInEpochFormat).format("MM/DD");
this.recentDonations.push({
donationDate: d.donationDate,
totalMoney: d.donationAmount
});
// }
console.log(this.recentDonations);
});
this.show = true;
}
},
async created() {
await setTimeout(this.request, 1000);
}
};
</script>
If you remove the if statement, the graph doesn't show any data
I am trying to reload the page after getting the response. But the issue I am facing is that it page reload goes into a loop and reloads continuously. How can I make it reload just once after getting the response.
create.vue
<script>
export default {
data () {
return {
agent: {
full_name: '',
address: '',
}
}
}
created() {
this.fetchAgent();
},
methods: {
fetchAgent() {
this.$axios.get(`/agent.json?${this.$route.query()}`)
.then(response => {
this.agent = response.data;
window.location.reload();
});
},
}
}
</script>
I need to make a pagination in my task, but it is not working.
I made two buttons to which I attached the "click" event and I registered a property in the "data". When I click on the buttons, the property changes and is written to the link and in the same way changes the current 10 posts to the following.
But for some reason it does not work as it should work. Can someone please explain what my mistake is and if you can suggest some articles on the subject of "pagination".
This is my html:
<button type="button" #click="counter -=1" class="prev">Prev</button>
<div class="counter">{{ counter }}</div>
<button type="button" #click="counter +=1" class="next">Next</button>
This is my Vue:
export default {
name: 'app',
data () {
return {
counter: 1,
zero: 0,
posts: [],
createTitle: '',
createBody: '',
visiblePostID: ''
};
},
created () {
axios.get('http://jsonplaceholder.typicode.com/posts?_start=${this.counter}+${this.zero}&_limit=10').then(response => {
this.posts = response.data;
});
}
};
The created method is called only when the component is created. To make the GET request everytime the counter increase or decrease use watches link.
Your example will become:
export default {
name: 'app',
data () {
return {
counter: 1,
zero: 0,
posts: [],
createTitle: '',
createBody: '',
visiblePostID: '',
}
},
watch: {
counter: function(newValue, oldValue) {
this.getData()
}
}
created(){
this.getData()
},
methods: {
getData() {
axios.get(`http://jsonplaceholder.typicode.com/posts?_start=${this.counter}+${this.zero}&_limit=10`).then(response => {
this.posts = response.data
})
}
}
}
You need to create a watcher for your counter that fires a load method. This way every time your counter changes you'll load in the correct posts for the page in your paginated results.
export default {
name: 'app',
data () {
return{
counter: 1,
...
}
},
created(){
this.loadPosts()
},
watch: {
counter(newVal, oldVal){
this.loadPosts()
}
},
methods: {
loadPosts(){
axios.get('http://jsonplaceholder.typicode.com/posts?_start=${this.counter}+${this.zero}&_limit=10')
.then(response => {
this.posts = response.data
})
}
}
}
Maybe this can help you. https://scotch.io/courses/getting-started-with-vue/vue-events-build-a-counter
I don't know vue, but looks like you need a function to load new data
I'm new to this, please be kind!
How do I transfer the value of the object that was returned to me in the console to the webpage? As of now, the balance value is in the console but it is not displayed on the page.
edit: If I wish to display the objects in the console separately, do I use myObj.key? eg. I want to display the value of balance on the left and the value of block on the right of my webpage, do I use myObj.balance and myObj.block ?
attached a screenshot of my browser
This is my code, do guide me, thank you!
<template>
<div class="box-card">
<p class="title-text">余额</p>
<p class="number-text">{{Balance}}</p>
</div>
</template>
<script>
export default {
data() {
return {
userId: 0,
// page config
currentPage: 1,
total: 0,
pageSize: 20,
userBalance: [],
Balance: '',
}
},
watch: {},
mounted() {
this.userId = this.$route.query["user_id"];
this.userId = 41;
this.getUserBalance();
this.getUserIncomeRecord();
console.log('hello');
},
methods: {
pageChange(val) {
this.currentPage = val;
},
getUserBalance() {
Core.Api.User.getUserBalance(this.userId).then(res => {
console.log(res);
res == this.Balance;
})
},
</script>
EDITED: If you want to print in a element with certain ID instead of console.log("WHAT YOU WANT TO PRINT") use this:
document.getlementById("YOUR ELEMENT ID HERE").innerHtml("WHAT YOU WANT TO PRINT");
If you use Jquery this is equivalent to the above code:
$("#ELEMENT ID HERE").html("WHAT YOU WANT TO PRINT");
make a slight change:
getUserBalance() {
Core.Api.User.getUserBalance(this.userId).then(res => {
console.log(res);
this.Balance = res;
})
},
I'm trying to display data in my vue component and I have an array that has object on it. If I try to use
<div class="bar">
{{playersStats[0]}}
</div>
it displays
{ "GP": 13, "GS": 6, "MPG": 20.74, "PPG": 12.85, "FGM": 4.46, "FGA": 9.77, "FGP": 0.46 }
but if I try using
<div class="bar">
<span v-if="playersStats[0]">{{playersStats[0].GS}}</span>
</div>
EDITED Javascript:
export default {
data: function(){
return {
showPlayersSelection: true,
selectedPlayers: [],
playersStats: []
}
},
methods: {
selectPlayers(player) {
if(this.selectedPlayers.length < 2){
this.selectedPlayers.push(player);
if(this.selectedPlayers.length == 2){
this.getPlayerStats(this.selectedPlayers[0][0], this.selectedPlayers[1][0]);
this.showPlayersSelection = false;
}
}
return false;
},
getPlayerStats(player1, player2) {
let self = this;
axios.get(config.API.URL + config.API.STATS, {
params: {
'player1Id': player1,
'player2Id': player2
}
})
.then( (response) => {
if(response.status == 200 && typeof(response.data) == 'object'){
self.playersStats = [];
self.playersStats.push(response.data[0][0]);
self.playersStats.push(response.data[1][0]);
}
});
},
}
}
It displays nothing even in DOM. How can I be able to display the data?
<span v-if="playersStats[0]">{{playersStats[0]["GS"]}}</span>
maybe u need this?