consume Api on the Quasar page - javascript

I'm creating a page for an App with the Quasar Framework, how do I consume this Api on the Quasar page (template)?
Could you help me make a v-for on the cards? How would you get the (articles title) of this object.
Quasar version 1.0, axios plugin.
Html:
<div class="" v-for="(articles, index) in posts" :key="index">
{{ articles.title }}
</div>
<script>
export default {
name: 'Novidades',
data () {
return {
posts: []
}
},
mounted () {
this.getPosts()
},
methods: {
getPosts () {
this.$axios.get('https://newsapi.org/v2/everything?q=bitcoin&from=2019-05-04&sortBy=publishedAt&apiKey=4feb77b8660e4904a51ecbcae805ce03')
.then((resp) => {
this.posts = resp.data
})
.catch((err) => {
console.error(err)
})
}
}
}
</script>

Ok. It seems that is a problem with how you manipulate JSON that you received.
It's easy to see that you have an array inside object received that is called "articles". And each element has a title. So basically what you have to do is, get this articles and v-for inside of it.
The code could be like
<template>
<div>
<div v-for="(article, index) in articles" :key="index">{{ article.title }}</div>
</div>
</template>
<script>
export default {
name: "Novidades",
data() {
return {
articles: []
};
},
mounted() {
this.getArticles();
},
methods: {
getArticles() {
this.$http
.get(
"https://newsapi.org/v2/everything?q=bitcoin&from=2019-05-04&sortBy=publishedAt&apiKey=4feb77b8660e4904a51ecbcae805ce03"
)
.then(resp => {
this.articles = resp.data.articles;
})
.catch(err => {
console.error(err);
});
}
}
};
</script>
And the code is running in here: https://codesandbox.io/s/vue-template-wf6tr

Related

How to get json data out of a scope after fetching data in Vue?

I'm new to Vue, javascript & Web development. Using Vue, I tried to recreate the moviedb app(from Brad's 50 JS Projects in 50 Days course).
I'm getting stuck and can't get the data out of a scope.
I've successfully retrieved data & destructured it.
But how can I get those values out of that scope (out of setMovies function) and use it in the Vue file (html template)?
Here's my code:
I've made the api_key private
<h1>MovieDesk</h1>
<div class="hero">
<!-- Search -->
<div class="search">
<form #submit.prevent="handleSearch">
<input type="text" placeholder="Search here..." />
<button #click="handleSearch">Search</button>
</form>
</div>
</div>
<!-- Movies -->
<div v-if="searchOn">
<SearchedMovies />
</div>
<div v-else>
<MovieList/>
</div>
</template>
<script>
// imports-------------------
import { ref } from "#vue/reactivity";
import MovieList from "../components/MovieList.vue";
import SearchedMovies from "../components/SearchedMovies.vue";
import { onMounted } from "#vue/runtime-core";
export default {
components: { MovieList, SearchedMovies },
setup() {
const searchOn = ref(false);
const api_url = ref(
"https://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=api_key&page=1"
);
const movies = ref([])
// getting the data ------------------------------
onMounted(() => {
fetch(api_url.value)
.then((res) => res.json())
.then((data) => {
console.log(data);
setMovies(data.results);
});
});
function setMovies(movies) {
movies.forEach((movie) => {
const { title, poster_path, vote_average, overview } = movie;
});
}
return { searchOn, setMovies };
},
};
</script> ```
In your setMovies function, You can set the response in the movies variable and then return that variable from your setup.
function setMovies(apiResponse) {
movies.value = apiResponse
}
return { movies };
Live Demo :
const { ref, onMounted } = Vue;
const App = {
setup() {
const movies = ref([])
onMounted(() => {
const apiResponse = [{
id: 1,
name: 'Movie 1'
}, {
id: 2,
name: 'Movie 2'
}, {
id: 3,
name: 'Movie 3'
}];
setMovies(apiResponse);
})
function setMovies(res) {
movies.value = res;
}
return {
movies
};
}
};
Vue.createApp(App).mount("#app");
<script src="https://unpkg.com/vue#next"></script>
<div id="app">
<pre>{{ movies }}</pre>
</div>
Add 'movies' to the return statement at the bottom of your code, then you should be able to render it.

How to fetch and display data on loading and also on search

I would like to fetch and display data on load. After this I would like to display data on search.
Now I only manage to display data on search keyup. I would like to show the list of artist when loading the page as well.
How to display data on load page
How to display data on search
Thanks in advance!
<template>
<div class="body">
<div class="searchBar">
<i class="bi bi-search"></i>
<input
placeholder="Search for artists"
type="text"
v-model="searchQuery"
#keyup="searchArtist"
/>
</div>
<div class="artists">
<div
className="artist__list"
v-for="artistResult in result"
:key="artistResult.id"
>
<h4>{{ artistResult.name }}</h4>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
import "./body.css";
export default {
data() {
return {
artists: [],
result: [],
searchQuery: "",
};
},
mounted() {
this.fetchArtists();
},
computed: {
filteredResult() {
const res = this.result;
const search = this.searchQuery;
if (!search) {
return res;
}
return res.filter((item) =>
item.name.toLowerCase().includes(search.toLowerCase())
);
},
},
methods: {
searchArtist() {
axios
.get(`http://localhost:3000/artists?q=${this.searchQuery}`)
.then((response) => {
this.result = response.data;
})
.catch((error) => {
console.error(error);
});
},
fetchArtists() {
axios
.get("http://localhost:3000/artists")
.then((response) => {
this.artists = response.data;
})
.catch((error) => {
console.error(error);
});
},
},
};
</script>
On fetch I need it to bind the api response to the empty array result.
return {
result: [],
searchQuery: "",
};
},
fetchArtists() {
axios
.get("http://localhost:3000/artists")
.then((response) => {
this.result = response.data;
})
.catch((error) => {
console.error(error);
});
},

Issue with Api call, not returning any response in Vuejs?

import axios from "axios";
export const routerid = (itemId) =>
axios.get("https://fakestoreapi.com/products?limit=" + itemId);
<template>
<div>
<div v-for="(item, key) in user" :key="key">
{{ item.price }} <br />
{{ item.description }} <br />
</div>
</div>
</template>
<script>
import { routerid } from "./routerid";
export default {
name: "User",
components: {},
data() {
return {
lists: [],
};
},
mounted() {
if (this.$route.params.id)
routerid(this.$route.params.id).then((r) => {
let obj = r.data;
this.lists = [{ ...obj }];
});
},
computed: {
user: function () {
return this.lists.filter((item) => {
return item.id === this.$route.params.id;
});
},
},
};
</script>
How to make axios url call with query params like this..https://fakestoreapi.com/products?limit=1 Where you can see in the url i have ...like ?limit=id.... So i am little bit confused about it..How to call
Did i correctly call the api or anything missing in the code logic. As of now, In my output, I cant see any response from the api.
Code:- https://codesandbox.io/s/cocky-ives-h19zm7?file=/src/components/routerid.js
Don't you want to fetch a product by its ID?
Then it rather would be:
export const routerid = async (itemId) =>
await axios.get("https://fakestoreapi.com/products/" + itemId);
https://codesandbox.io/s/silly-nightingale-ixz8tr

How do I call Axios on prop change in Vue?

On the change of the value id, I would like to make a JSON call via Axios and update necessary parts of the page. How do I do that? Currently, I have mounted and activated and they do not seem to be working...
Code:
const Home = {
template: `
<div class="user">
<h2>user {{ id }}</h2>
<h2>{{ info }}</h2>
bet
</div>
`,
props: {
id: {
type: String,
default: 'N/A'
}
},
data () {
return {
info: null
}
},
activated () {
axios
.get('https://api.coindesk.com/v1/bpi/currentprice.json',
{ params: { id: id }}
)
.then(response => (this.info = response))
},
mounted() {
axios
.get('https://api.coindesk.com/v1/bpi/currentprice.json')
.then(response => (this.info = 'response'))
}
}`
You can listen to id prop change by using watch:
watch: {
id: function(newId) {
axios
.get('https://api.coindesk.com/v1/bpi/currentprice.json',
{ params: { id: newId }}
)
.then(response => (this.info = response))
}
}
Here is a little demo based on the code that you shared that shows how watch reacts to id prop change. Wrapper component below is solely for demonstration purpose as something that triggers id value change.
const Home = {
template: `
<div class="user">
<h2>user {{ id }}</h2>
<h2>{{ info }}</h2>
bet
</div>
`,
props: {
id: {
default: 'N/A'
}
},
data () {
return {
info: null
}
},
mounted() {
axios
.get('https://api.coindesk.com/v1/bpi/currentprice.json')
.then(response => (this.info = 'response'))
},
watch: {
id: function(newId) {
console.log(`watch triggered, value of id is: ${newId}`);
axios
.get('https://api.coindesk.com/v1/bpi/currentprice.json',
{ params: { id: newId }}
)
.then(response => (this.info = response))
}
}
}
const Wrapper = {
template: '<div><home :id="id" /></div>',
components: { Home },
data() {
return {
id: 0
}
},
mounted() {
const limit = 5;
const loop = (nextId) => setTimeout(() => {
console.log(`#${nextId} loop iteration`);
if (nextId < limit) {
this.id = nextId;
loop(nextId + 1);
}
}, 3000);
loop(this.id);
}
}
new Vue({
el: '#app',
components: { Wrapper }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js" ></script>
<div id="app">
<wrapper />
</div>

VueJS How to pass props between two components using <router-view>

I'm new to vue.js and I'm tryeing to build a little application, where I in one case need to pass a prop between two components. For some reason it does not work and I don't know why.
Here is the first component, the Playlist.Vue component:
<template>
<div class="playlists-con">
<div class="playlists">
<h1>Available Playlists for category: {{id}}</h1>
<ul>
<router-link v-for="playlist in playlists" :to="`details/${playlist.id}`" tag="li" active-class="active" exact>
<div class="playlist-wrapper">
<div class="imgWrap">
<img :src="playlist.images[0].url" />
</div>
<a>{{playlist.name}}</a>
</div>
</router-link>
</ul>
</div>
<div>
<router-view category="id"></router-view>
</div>
</div>
</template>
<script>
export default {
data() {
return {
id: this.$route.params.id,
playlists : []
}
},
watch: {
'$route'(to, from) {
this.id = to.params.id
}
},
methods: {
fetchPlaylist() {
this.$http.get('' + this.id + '/playlists')
.then(response => {
return response.json()
})
.then(data => {
const playlist_items = data.playlists.items;
for (let key in playlist_items) {
this.playlists.push(playlist_items[key])
}
})
}
},
created() {
this.fetchPlaylist();
}
}
</script>
from the Playlist component, I'm supposed to be able to get to the Playlist details. I also want to pass the category prop to the PlaylistDetails.vue, so I tried to do <router-view category="id"></router-view> - but that does not work.
PlaylistDetails.vue component (where I want to display the category prop, passed from the Playlist.vue component) :
<template>
<div class="playlist-details">
<router-link :to="`/categories/${category}`">Go to playlists</router-link>
<h1>Playlist Details for Playlist: <span class="playlist-name">{{playlistName}}</span></h1>
<h1>category: {{ category }}</h1>
<ul>
<li v-for="track in tracks">
<p>{{ track.track.artists[0].name}} - {{ track.track.name }}</p>
</li>
</ul>
</div>
</template>
<script>
export default {
props: ['category'],
data() {
return {
id: this.$route.params.id,
tracks : [],
playlistName: ''
}
},
watch: {
'$route'(to, from) {
this.path = from.params.path
}
},
beforeRouteEnter(to, from, next) {
if (true) {
next();
} else {
next(false);
}
},
methods: {
fetchPlaylistDetails() {
this.$http.get('https://api.spotify.com/v1/users/spotify/playlists/' + this.id)
.then(response => {
return response.json()
})
.then(data => {
const playlist_tracks = data.tracks.items;
for (let key in playlist_tracks) {
this.tracks.push(playlist_tracks[key])
}
this.playlistName = data.name;
})
}
},
created() {
this.fetchPlaylistDetails();
}
}
</script>
What am I doing wrong?
UPDATE
Here is my router configuration:
export const routes = [
{
path: '', default: App
},
{
path: '/categories/:id/playlists', props: true, component: Playlists
},
{
path: '/categories/:id/details/:id', component: PlaylistDetails, props: true, beforeEnter: (to, from, next) => {
next();
}},
{path: '*', redirect: '/'}
]
You are half way there, you defined props:true on the route, which means every dynamic property that is matched in the url would be passed as a prop, so :
//this will pass 'id' as a prop to the playlist component
{
path: '/categories/:id/playlists', props: true, component: Playlists
},
So inside the playlist component you'll have this:
props: ['id'],
data() {
return {
playlists : []
}
},
The same is true for the details component:
//change the name of the param to distinguish it from the category id
{
path: '/categories/:id/details/:detailsId', component: PlaylistDetails, props: true, beforeEnter: (to, from, next) => {
next();
}},
And in PlaylistDetails.vue:
props: ['detailsId'],
....
methods: {
fetchPlaylistDetails() {
this.$http.get('https://api.spotify.com/v1/users/spotify/playlists/' + this.detailsId)
.then(response => {
return response.json()
})
.then(data => {
const playlist_tracks = data.tracks.items;
for (let key in playlist_tracks) {
this.tracks.push(playlist_tracks[key])
}
this.playlistName = data.name;
})
}
},
There're 2 ways to pass data between non-parent components. I would recommend to take a look at them, before trying solve issue with router-view:
Using Vue.bus
Using Vuex

Categories

Resources