vuejs limit request to first 10 items - vue.js

I am making async promise that supposed to map in vuejs. I simply need to limit the request to the first 10 items...just a way to limit so it doesnt go through all results. The method i want to limit is getCodeLinkage2
new Vue({
el: "#app",
data: {
box:[],
Modules:[],
},
mounted:function(){
getCodeLinkage2();
},
methods: {
async getCodeLinkage2() {
const data = await Promise.all(this.Modules.map(Modules => this.request('GET', `https://example.com/${Modules.Identifier}/content/voc`)));
data.forEach(item => {
alert("data");
this.box.push(item);
});
console.log(this.box);
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ul>
<li v-for="mod in Modules">
{{ mod.Code}}<br>
{{ mod.Identifier}}
</li>
</ul>
</div>

You should filter out the first 10 items before requesting the data. i in this case is the index, we only look at items in the Modules array that have an index in the array smaller than our cutoff.
const cutoff = 10
const data = await Promise.all(
this.Modules
.filter((_,i) => i < cutoff)
.map(Modules => this.request('GET', `https://example.com/${Modules.Identifier}/content/voc`)));

Related

Nuxt.js Hackernews API update posts without loading page every minute

I have a nuxt.js project: https://github.com/AzizxonZufarov/newsnuxt2
I need to update posts from API every minute without loading the page:
https://github.com/AzizxonZufarov/newsnuxt2/blob/main/pages/index.vue
How can I do that?
Please help to end the code, I have already written some code for this functionality.
Also I have this button for Force updating. It doesn't work too. It adds posts to previous posts. It is not what I want I need to force update posts when I click it.
This is what I have so far
<template>
<div>
<button class="btn" #click="refresh">Force update</button>
<div class="grid grid-cols-4 gap-5">
<div v-for="s in stories" :key="s">
<StoryCard :story="s" />
</div>
</div>
</div>
</template>
<script>
definePageMeta({
layout: 'stories',
})
export default {
data() {
return {
err: '',
stories: [],
}
},
mounted() {
this.reNew()
},
created() {
/* setInterval(() => {
alert()
stories = []
this.reNew()
}, 60000) */
},
methods: {
refresh() {
stories = []
this.reNew()
},
async reNew() {
await $fetch(
'https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty'
).then((response) => {
const results = response.slice(0, 10)
results.forEach((id) => {
$fetch(
'https://hacker-news.firebaseio.com/v0/item/' +
id +
'.json?print=pretty'
)
.then((response) => {
this.stories.push(response)
})
.catch((err) => {
this.err = err
})
})
})
},
},
}
</script>
<style scoped>
.router-link-exact-active {
color: #12b488;
}
</style>
This is how you efficiently use Nuxt3 with the useLazyAsyncData hook and a setInterval of 60s to fetch the data periodically. On top of using async/await rather than .then.
The refreshData function is also a manual refresh of the data if you need to fetch it again.
We're using useIntervalFn, so please do not forget to install #vueuse/core.
<template>
<div>
<button class="btn" #click="refreshData">Fetch the data manually</button>
<p v-if="error">An error happened: {{ error }}</p>
<div v-else-if="stories" class="grid grid-cols-4 gap-5">
<div v-for="s in stories" :key="s.id">
<p>{{ s.id }}: {{ s.title }}</p>
</div>
</div>
</div>
</template>
<script setup>
import { useIntervalFn } from '#vueuse/core' // VueUse helper, install it
const stories = ref(null)
const { pending, data: fetchedStories, error, refresh } = useLazyAsyncData('topstories', () => $fetch('https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty'))
useIntervalFn(() => {
console.log('refreshing the data again')
refresh() // will call the 'topstories' endpoint, just above
}, 60000) // every 60 000 milliseconds
const responseSubset = computed(() => {
return fetchedStories.value?.slice(0, 10) // optional chaining important here
})
watch(responseSubset, async (newV) => {
if (newV.length) { // not mandatory but in case responseSubset goes null again
stories.value = await Promise.all(responseSubset.value.map(async (id) => await $fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`)))
}
})
function refreshData() { refreshNuxtData('topstories') }
</script>

Cant store api data called by axios in array through mounted, unless clicking on <Root> element from vue devtools (in browser)

i'm using axios to get data from api and store in an array after mounting then run a search query in the array later on, but it's not working unless i click on Root element in browsers Vue developer tools, after i click on vue Root element from vue dev tool everything works fine.Here is my code..
<script type="module">
const vueApp = new Vue({
el: "#pos",
data: {
searchTerm: "",
allProducts: [],
selectedProducts: [],
suggestions: []
},
mounted: function (){
axios.get("api/products").then( res => this.allProducts = res.data );
},
methods: {
select(item){
this.selectedProducts.push(item);
this.suggestions = [];
}
},
computed:{
matches(){
if(!this.searchTerm) return;
this.suggestions = this.allProducts.filter(sP=>(sP.prod_name).includes(this.searchTerm));
}
}
});
</script>
//HTML below------------------
<div id="pos">
<input type="text" v-model="searchTerm">
<ul v-for="match in suggestions">
<li #click="select(match)">
{{match.prod_name}}
</li>
</ul>
<table>
<tr v-for="(product,i) in selectedProducts">
<td>#{{product.prod_name}}</td>
</tr>
</table>
</div>
const vueApp = new Vue({
el: "#pos",
data: {
searchTerm: "",
allProducts: [],
selectedProducts: [],
suggestions: []
},
mounted: function() {
axios.get("api/products").then(res => this.allProducts = res.data);
},
methods: {
select(item) {
this.selectedProducts.push(item);
this.suggestions = [];
}
},
computed: {
matches() {
if (!this.searchTerm) return;
this.suggestions = this.allProducts.filter(sP => (sP.prod_name).includes(this.searchTerm));
}
}
});
<div id="pos">
<input type="text" v-model="searchTerm">
<ul v-for="match in suggestions">
<li #click="select(match)">
{{match.prod_name}}
</li>
</ul>
</div>
As I mentioned in the comments on your question, this is an error I cannot seem to understand how you are getting. I sense there is information that we are not being presented with.
As such, here is a quick "working" example of fetching items from the mounted lifecycle hook in a component. Note: If you are creating the component via a Single-File Component (.vue files) then don't worry too much about the declaration, pay attention only to the data and mounted methods.
const App = Vue.component('App', {
template: `<div>
<input v-model="searchTerm" type="search">
{{items.length}} results fetched
</div>`,
data() {
return {
searchTerm: '',
items: []
}
},
mounted() {
//Timeout used to mimic axios query
setTimeout(()=> this.items= [1,2,3,4], 1000)
}
});
const app = new App({
el: '#app'
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">Placeholder</div>
Edit
The code you have given us after your update seems to be working just fine. See the below snippet.
I noticed you are looping over suggestions but that value is never updated anywhere in your given code.
const vueApp = new Vue({
el: "#pos",
data: {
searchTerm: "",
allProducts: [],
selectedProducts: [],
suggestions: []
},
mounted: function() {
setTimeout(() => this.allProducts = [1,2,3,4,5], 1000);
},
methods: {
select(item) {
this.selectedProducts.push(item);
this.suggestions = [];
}
},
computed: {
matches() {
if (!this.searchTerm) return;
this.suggestions = this.allProducts.filter(sP => (sP.prod_name).includes(this.searchTerm));
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="pos">
<input type="text" v-model="searchTerm">
<ul v-for="match in suggestions">
<li #click="select(match)">
{{match.prod_name}}
</li>
</ul>
{{allProducts.length}} results loaded
</div>
mounted: function(){
var _self = this;
axios.get("api/products").then( res => _self.allProducts = res.data );
}

Filtering with substrings and watching for change but no update

I am working with substrings and watchers in vuejs. I have an issue. In my data model, I will end up having about 20 states that all have a code added to each of them. I filter out the code to just the first letters--that way I should be able too write some conditional render that will display the state name which would be indicative of the code. For instance if I have NY9830 OR NY83793, the substring cuts it down to just NY and I am trying to make the text update to New York. Its not updating and I added a watch to the v-model. I will have like 20 conditions for different states so, the easiest way to do this would be helpful.
new Vue({
el: "#liveapp",
data: function() {
return {
Office: 'NY006 '
}
},
methods: {
},
watch: {
stateValue: function() {
if (this.office == "NY") {
alert("display New York");
this.stateValue = "New York";
} else if (this.office == "LA") {
alert("display Louisiana");
this.stateValue = "Louisiana";
}
}
},
filters: {
liveSubstr: function(string) {
return string.substring(0, 2);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="liveapp">
<h2>Todos:</h2>
<p v-model="stateValue">{{ Office | liveSubstr}}</p>
</div>
If I'm reading your question correctly, what I think you want is a filter that can transform an office code like "NY9830" into a full state name like "New York".
You can back the filter with a map of state abbreviations to full-names. For example
const states = new Map([
['NY', 'New York'],
['LA', 'Louisiana'],
['TX', 'Texas']
])
Vue.filter('state', value => {
return states.get(value.substring(0, 2)) || 'Unknown'
})
new Vue({
el: '#app',
data: () => ({ offices: [] }),
created() {
// simulate remote request
setTimeout(() => {
this.offices = ['NY9830', 'NY83793', 'LA7474', 'TX0894']
}, 1000)
}
})
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<ul>
<li v-for="office in offices" :key="office">
{{ office }} - {{ office | state }}
</li>
</ul>
</div>

Filter data from database using v-for

Here I tried making a const data inside the script(vue js).
data() {
return {
event: [],
items: [
[id: '1', month:'January', date:'01'],
[id: '2', month:'February', date:'03'],
]}
}
filter(val) {
let items = this.items;
let filter = items.filter(el => el.month === val);
this.event = filter;
}
And had this in my v-for
<h1 v-for="(item, id) in event" v-bind:key="id"></h1>
<p>{{ items.month }}</p>
It loops the filtered items from the empty event array.
Since my const data is too many. I tried creating an API.
And this is how I get the data from database.
data() {
return {
Items: [],
}
}
getHoliday(){
getTest.getHoliday()
.then(response =>{
this.Items = response.data;
})
},
And loop through it using v-for
<h1 v-for="(Item, id) in Items" v-bind:key="id"></h1>
<p>{{ Item.month }}</p>
From here, I only know how to call the specific data through mustache. I can't do the filter that I use when using const data.
If I understand the question correctly, you can filter data from backend via computed properties.
computed: {
filteredItems() {
return this.Items.filter((item) => {...});
},
},
in your template you can iterate over this new property
<h1 v-for="(Item, id) in filteredItems" v-bind:key="id">{{ Item.month }}</h1>

how can i populate an axios get data array and pass it to a Vuejs component props to do list rendering in the component

Given I have a component called upload-csv
Vue.component('upload-csv',{
props:['clientnames'],
template:`
<ul>
<li v-for="clientname in clientnames">{{ clientname.name }}</li>
</ul>
`
});
Then a Vue Instance
new Vue({
el:"#upload-csv-component",
data:{
loadurl:'http://localhost/startup/public/index.php/loadnames',
clientnames:[]
},
mounted:function(){
axios.get(this.loadurl)
.then(function(response){
this.clientnames = response.data;
})
.catch(function(error){});
}
});
Wish to use it this way
<div id="upload-csv-component">
<upload-csv :clientnames="clientnames"></upload-csv>
</div>
But the list is not rendering; I have changed mounted hook to beforeMount yet the list is not rendering.
Please can someone suggest a way to solve this problem.
Use an arrow function to keep access to this inside the axios request:
mounted(){
axios.get(this.loadurl)
.then((response) => {
this.clientnames = response.data
})
}
(great answer here about this context)
It would appear that axios requires the fat arrow syntax, as shown here
Using Axios to Consume APIs
console.clear();
Vue.component('upload-csv',{
props:['clientnames'],
template:`
<ul>
<li v-for="clientname in clientnames">{{ clientname.name }}</li>
</ul>
`
});
new Vue({
el:"#upload-csv-component",
data () {
return {
loadurl:'https://jsonplaceholder.typicode.com/users',
clientnames:[]
}
},
mounted:function(){
axios.get(this.loadurl)
.then(response => {
console.log(response);
this.clientnames = response.data;
})
.catch(function(error){});
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="upload-csv-component">
<h1>Clients</h1>
<upload-csv :clientnames="clientnames"></upload-csv>
</div>