I know how to get all the data from the json server, but now I would like to know if there is a way to call a certain number of say products, because I want to add a button when the user clicks on it and then make another call and display a few more products on the page...I am using Vue, and this is just an exercise project and i am only creating view, so thats why i am using json server
<template>
<div v-for="product in products" :key="product.name">
<Product :product="product" />
</div>
</template>
<script>
data() {
return {
products: []
}
},
async created() {
try{
const response = await axios.get('http://localhost:3000/products')
this.products = response.data
} catch(err) {
console.log(err)
}
}
</script>
You can use the _limit and _page query parameters in your route.
// Get products 1-10
const response = await axios.get('http://localhost:3000/products?_limit=10&_page=1')
// Get products 11-20
const response = await axios.get('http://localhost:3000/products?_limit=10&_page=2')
// Get products 31-45
const response = await axios.get('http://localhost:3000/products?_limit=15&_page=3')
Related
I am trying to update 'this.counts' value in my axios called URL when a button is clicked. Can anyone help me to work this out? Thanks
.get(
"https://myurl/results.json" +
query +
`&num_ranks=$**{this.counts}**`
data: function () {
return {
counts: 2
};
methods: {
//number added to the Axios URL to display load more results
loadMore() {
if (this.loadMore) {
this.counts += 10;
}
},
}
<button
#click="loadMore">
Load more {{ counts }}
</button>
One thing I found missing is, that on the counts variable's update, the Axios API should be re-triggered to fetch the new response. And if your re-triggering it then it should work. You might need to check your API then.
Here is a dummy API demo that is taking counts as the query param and fetching the response every time on the counts variable's update.
Vue.config.productionTip = false;
var app = new Vue({
el: '#app',
data() {
return {
counts: 0
}
},
methods: {
loadMore() {
if (this.loadMore) {
this.counts += 1;
this.getMore()
}
},
getMore() {
console.clear()
// Axios call here
axios.get(`https://jsonplaceholder.typicode.com/comments?postId=${this.counts}`).then(res => {
console.log(res)
})
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.3.2/axios.min.js" integrity="sha512-NCiXRSV460cHD9ClGDrTbTaw0muWUBf/zB/yLzJavRsPNUl9ODkUVmUHsZtKu17XknhsGlmyVoJxLg/ZQQEeGA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="loadMore">Load more {{ counts }}</button>
</div>
What you need is using params in your axios call.
axios.get('https://myurl/results.json', { params: { num_ranks: this.counts } });
parameters will append to the url your are calling.
If you have more parameters just put them in params: {...}
axios.get('https://myurl/results.json', {
params: {
param1: this.result,
param2: this.result2,
param3: this.result3
}
});
Create a specific function for axios API request and call it whenever the button clicked. (Call it in loadMore().)
<template>
<button #click="loadMore">Load more {{ counts }}</button>
</template>
<script>
export default {
data() {
return {
counts: 0
}
},
methods: {
loadMore() {
if (this.loadMore) {
this.counts += 10;
this.getMore()
}
},
getMore() {
// Axios call here
axios.get("https://myurl/results.json" + query + `&num_ranks=$**{this.counts}**`)
}
}
}
</script>
You can use URLSearchParams to get the url param by name and modify in your code. Something like this:
const url = window.location.href // get the url from current page
const searhParams = new URLSearchParams(url);
if (searchParams.has('name of the param in url')) {
let count = searchParams.get('param in url');
loadMore(count); // you pass as a param to loadMore function or do it inside that function
}
Here's the doc for more help: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
The first problem is that when getDetails(‘multiple’, ‘2’) function is called inside HTML, it takes some time until de data is displayed from v-for.
The second problem is that when I call the console.log(userDetails) from inside of anotherFunction() I got the undefined answer. It doesn’t wait for the this.getDetails(‘multiple’, ‘1’) to execute completely.
How can I improve the time for rendering, or should I use another way to display de data?
How can I make the second function to wait until the first function is complete?
VUE version: 2.7.10
<div id="app">
<p v-for="item in userDetails">item is displayed</p> //
<button #click="anotherFunction()">Click Me!</button>
</div>
<script>
export default {
name: 'App',
data: {
userDetails: []
}
}
// axios function
getDetails(actionType, idUser) {
axios.post("https://example.com/link", {
Username: username
}).then(response => {
const result = response.data;
// push data into variable
this.userDetails.push(result[0])
}).catch(error => {
this.showError('Error', 4000);
console.error('Error:' + error);
});
// another function from where I want to call the axios function
anotherFunction() {
this.getDetails('multiple', '1')
// call the userDetails into another function will output "undefined"
console.log(this.userDetails);
}
<template>
<div class="home">
<h1>BPMN Lint Analyzer</h1>
<!-- Get File from DropZone -->
<DropZone #drop.prevent="drop" #change="selectedFile"/>
<span class="file-info">File:{{dropzoneFile.name}}</span>
<button #click="sendFile" >Upload File</button>
<!-- Display Response Data (Not Working)-->
<div v-if="showResponseData">
<p>Testing: {{responseData}}</p>
</div>
</div>
</template>
<script>
import DropZone from '#/components/DropZone.vue'
import {ref} from "vue"
import axios from 'axios'
export default {
name: 'HomeView',
components: {
DropZone
},
setup(){
let dropzoneFile = ref("")
//Define Response variable and visibility toggle
var responseData=''
// var showResponseData = false
//Methods
const drop = (e) => {
dropzoneFile.value = e.dataTransfer.files[0]
}
const selectedFile = () => {
dropzoneFile.value = document.querySelector('.dropzoneFile').files[0]
}
//API Call
const sendFile = () => {
let formData = new FormData()
formData.append('file', dropzoneFile.value)
axios.post('http://localhost:3000/fileupload', formData,{
headers: {
'Content-Type':'multipart/form-data'
}
}).catch(error => {
console.log(error)
}).then(response => {
responseData = response.data
console.log(responseData);
})
// showResponseData=true
}
return{dropzoneFile, drop, selectedFile, sendFile}
}
}
</script>
I'm trying to pass the response from sendFile, which is stored in responseData back to the template to display it in a div to begin with. I'm not sure if a lifecycle hook is needed.
Current output:
I played around with toggles, I tried to convert everything to options API. Tried adding logs but I'm still struggling to understand what I'm looking for.
Unfortunately I am stuck with the Composition API in this case even if the application itself is very simple. I'm struggling to learn much from the Docs so I'm hoping to find a solution here. Thank you!
You need to make responseData reactive, so try to import ref or reactive from vue:
import {ref} from 'vue'
then create your variable as a reactive:
const responseData = ref(null)
set data to your variable:
responseData.value = response.data
in template check data:
<div v-if="responseData">
<p>Testing: {{responseData}}</p>
</div>
finally return it from setup function (if you want to use it in template):
return{dropzoneFile, drop, selectedFile, sendFile, responseData}
I would like to know is there is a way to do something like this without backend. I am calling all data from json server and displaying on home page:
async created() {
try{
const products = await axios.get('http://localhost:3000/products')
this.products = products.data
} catch(err) {
console.log(err)
}
}
Now when i click any of these products i would like to redirect user to new page and would like to display data of that specific object from json server.
What i have built for now is when user click on any product he gets redirected to route /product, and everything is hardcoded there, no dynamic data.
I hope my question is clear, thank you everybody.
You should consider using Vuex for this.
Move your method from created() to vuex's action and then call it in the hook.
The Vuex store's code is gonna be something like this:
state: {
products: []
},
getters: {
getProductById: (state) => (id) => state.products.find(product.id === id)
},
mutations: {
SET_PRODUCTS(state, products) {
state.products = products
}
},
actions: {
// this one is to call from the hook
fetchProducts({ commit }) {
return axios.get('http://localhost:3000/products').then(res => {
commit('SET_PRODUCTS', res.data)
})
}
}
Then call something like this from the component you're redirecting from:
<router-link
:to="{
name: 'Product', // im assuming this is the /product route's name
params: {
id: product.id // product.id is the id of your specific object your clicked on
}"
>
{{ product.productName }}
</router-link>
In your <Product /> component, you get the specific object by id from your Vuex store by using the getProductById() getter.
In your template:
...
<!-- the id we've passed as a route params -->
<h1>{{ getProductById($route.params.id) }}</h1>
...
I have a basic CRUD rails 5.2 API with a Story model. I am building a Vuejs front end to consume it. Currently, The index view at /stories successfully pulls in data from the server. I can also add stories to the database via NewStory.vue at stories/new. I am trying now to show a single story on a page at stories/:id. The api server currently shows the single result I need at v1/stories/:id.
here is what I have at services/Api.js:
import axios from 'axios'
export default() => {
return axios.create({
baseURL: `http://localhost:3000/v1`
})
}
in StoriesService.js:
import Api from '#/services/Api'
export default {
fetchStories () {
return Api().get('stories')
},
addStory (params) {
return Api().post('stories', params)
},
getStory (params) {
return Api().get('/stories/1')
}
}
in ViewStory.vue:
<template>
<div class="stories">
<h1>Story</h1>
<div v-if="story" class="table-wrap">
<div>
<router-link v-bind:to="{ name: 'NewStory' }" class="">Add
Story</router-link>
</div>
<p>Title: {{story.attributes.title}}</p>
<p>Overview: {{story.attributes.description}}</p>
</div>
<div v-else>
The story with id:{{params}} does not exist <br><br>
<!-- <router-link v-bind:to="{ name: 'NewStory' }"
class="add_story_link">Add Story</router-link> -->
</div>
</div>
</template>
<script>
import StoriesService from '#/services/StoriesService'
export default {
name: 'story',
data () {
return {
title: '',
description: ''
}
},
mounted () {
this.getStory()
},
methods: {
async getStory (params) {
const response = await StoriesService.getStory(params)
this.story = response.data
console.log(this.story)
}
}
}
</script>
With the id of the record hard coded, in the Network tab, I see the request being made to the api and the correct record being retrieved.
However, if I change the getStory call to return Api().get('/stories/', params) I get a 304 response and can't retrieve data.
My question is how to get StoriesService.js to return localhost:3000/v1/stories/params.id, where params.id is the id of the story referenced in the url.
Currently you are not passing in any params to getStory, so you need to get them from the this.$route.params
async getStory () {
const response = await StoriesService.getStory(this.$route.params)
this.story = response.data
console.log(this.story)
}
Beside that axios only supports query string parameters so if your url looks like /stories/someId then you need to build it yourself in getStory:
getStory (params) {
return Api().get(`/stories/${params.id}`)
}
Additionally your data object is missing the story property:
data () {
return {
story: null,
title: '',
description: ''
}
},