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

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);
});
},

Related

Vuex global state change does not trigger re-render component in v-for loop in Nuxt

I have difficult to use vuex global state combine with re-render child-component in Vue.js.
The global state is mutated but does not re-render its data in v-for loop.
All list of data is rendered, but when the new data changes, component in /blog does not change data in it.
Here is some code:
/store/index.js
export const state = () => ({
allData: [],
})
export const getters = {
getAllData: (state) => state.allData,
}
export const mutations = {
GET_DATAS(state, payload) {
state.allData = payload
},
UPDATE_DATA(state, payload) {
const item = state.allData[payload.index]
Object.assign(item, payload)
},
}
export const actions = {
getDatas({ commit, state }, payload) {
return fetch(`URL_FETCH`)
.then((data) => data.json())
.then((data) => {
commit('GET_DATAS', data)
})
.catch((err) => console.log(err))
},
updateData({ commit, state }, payload) {
commit('UPDATE_DATA', payload)
},
}
in /layouts/default.vue
beforeCreate() {
this.$store.dispatch('getDatas').then(() => {
connectSocket()
})
},
methods: {
connectSocket() {
// connect & received message from socket
// received message from socket
this.$root.$emit('updateData', {
index: 12,
price: 34,
change: 56,
percent: 78,
})
},
},
and in /pages/blog/index.vue
<template>
<div>
<div
v-for="index in getAllData"
:key="index.name"
class="w-100 grid-wrapper"
>
<div>{{ index.price }}</div>
<div>{{ index.change }}</div>
<div>{{ index.percent }}</div>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
data() {
return {}
},
computed: {
...mapGetters(['getAllData']),
},
mounted() {
this.$root.$on('updateData', (item) => {
this.$store.dispatch('updateData', {
index: item.index,
price: item.price,
percent: item.percent,
change: item.change,
})
})
},
}
</script>
Here is a complete example on how to use Vuex and load the data efficiently into a Nuxt app (subjective but using good practices).
/pages/index.vue
<template>
<div>
<main v-if="!$fetchState.pending">
<div v-for="user in allData" :key="user.id" style="padding: 0.5rem 0">
<span>{{ user.email }}</span>
</div>
</main>
<button #click="fakeUpdate">Update the 2nd user</button>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex'
export default {
data() {
return {
mockedData: {
name: 'John Doe',
username: 'jodoe',
email: 'yoloswag#gmail.com',
phone: '1-770-736-8031 x56442',
website: 'hildegard.org',
},
}
},
async fetch() {
await this.setAllData()
},
computed: {
...mapState(['allData']),
},
methods: {
...mapActions(['setAllData', 'updateData']),
fakeUpdate() {
this.updateData({ index: 1, payload: this.mockedData })
},
},
}
</script>
/store/index.js
import Vue from 'vue'
export const state = () => ({
allData: [],
})
export const mutations = {
SET_ALL_DATA(state, payload) {
state.allData = payload
},
UPDATE_SPECIFIC_DATA(state, { index, payload }) {
Vue.set(state.allData, index, payload)
},
}
export const actions = {
async setAllData({ commit }) {
try {
const httpCall = await fetch('https://jsonplaceholder.typicode.com/users')
const response = await httpCall.json()
commit('SET_ALL_DATA', response)
} catch (e) {
console.warn('error >>', e)
}
},
updateData({ commit }, { index, payload }) {
commit('UPDATE_SPECIFIC_DATA', { index, payload })
},
}

consume Api on the Quasar page

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

AJAX Search with Laravel and Vue empty Results

i want to build a search with ajax and vue.
So i have a model called "file" here all my files
then i have a controller called searchcontroller.php
public function search(Request $request)
{
$files = File::where('name', $request->keywords)->get();
return response()->json($files);
}
this is my route
Route::post('/', 'SearchController#search');
and i have a search.vue
<template>
<div>
<input type="text" v-model="keywords">
<ul v-if="results.length > 0">
<li v-for="result in results" :key="result.id" v-text="result.name"></li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
keywords: null,
results: []
};
},
watch: {
keywords(after, before) {
this.fetch();
}
},
methods: {
fetch() {
axios.get('/', { params: { keywords: this.keywords } })
.then(response => this.results = response.data)
.catch(error => {});
}
}
}
</script>
if i type a letter the resposce work i think but it shows me 10000 list points with an emtpy result
i wanna do it like here: https://jsfiddle.net/hej7L1jy/2/
if i do:
console.log(this.results);
console.log(this.keywords);
i get for results:
Array(0)
and the keyword works
public function search(Request $request)
{
$files = File::where('name', 'like', '%' . $request->get('keywords') . '%')->get();
return response()->json($files);
}
<template>
<div>
<input type="text" v-model="keywords">
<ul v-if="results.length > 0">
<li v-for="result in results" :key="result.id">{{ result.name }}</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
keywords: null,
results: []
};
},
watch: {
keywords(after, before) {
this.fetch();
}
},
methods: {
fetch() {
axios.post('/', { params: { keywords: this.keywords } })
.then(response => this.results = response.data)
.catch(error => {});
}
}
}
</script>
I GOT IT :)
Controller:
public function search(Request $request)
{
$files = DB::table('files')->where('name', 'like', '%' . $request->get('keywords') . '%')->get();
return response()->json($files);
}
Route:
Route::get('/search', 'SearchController#search');
Vue:
<template>
<div>
<input type="text" v-model="keywords">
<ul v-if="results.length > 0">
<li v-for="result in results" :key="result.id">{{ result.name }}</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
keywords: null,
results: []
};
},
watch: {
keywords(after, before) {
this.fetch();
}
},
methods: {
fetch() {
axios.get('/search', { params: { keywords: this.keywords } })
.then(response => this.results = response.data)
.catch(error => {});
}
}
}
</script>
i edited the where function in my controller and i needed a "get" method , not a "post" :)

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>

How to update fetched data to view next or previous page - Paginated

I am fetching data from a API,then displaying it to the page. I have achieved that,
Now I want to build a next and previous button to render the next page of information.
One of the data returned is metadata to links that can be attached to the base url. I got the data and updated it in my state as:
articlePages: []
the data is structured as :
"metadata": {
"pagination": {
"next_page": "/api/articles/ios_index?page=2",
"current_page": "/api/articles/ios_index?page=1",
"previous_page": "/api/articles/ios_index?page=0"
}
}
How should I build the functions for previous and next, so that they attach the right string to the base url, then fetch the new data?
Here is the response I receive then I update my state:
Response Format:
"metadata": {
"pagination": {
"next_page": "/api/articles/ios_index?page=2",
"current_page": "/api/articles/ios_index?page=1",
"previous_page": "/api/articles/ios_index?page=0"
}
}
"data" :{
"id": 713,
"url": "https:sample.-sale",
"title": "The World According to Eddie Huang",
"published_at": "2017-08-29T04:00:00.000Z",
"published": true,
"hero": "https://d1qz9pzgo5wm5k./CPG9crJHRqSPKQg9jymd",
"listings": [],
"tag_list": [
"eddie-huang",
"television"
],
"franchise": "The Drop",
"slug": "eddie-huang-interview-sale",
"author": "Lawrence Schlossman",
"content_type": "long",
"position": "feature"
}
Here is a snippet of my code, any help is appreciated :
import React from 'react';
import axios from 'axios';
export default class ArticleApi extends React.Component {
constructor() {
super();
this.state = {
blogs: "",
articlePages: []
}
}
fetchData = () => {
axios.get(`https:sample.sale/api/articles/ios_index`)
.then(res => {
this.setState({
blogs: res.data.data,
blogPages: res.data.metadata
})
})
.catch(error => {
return ('Looks like there was a problem: \n', error);
});
}
componentDidMount() {
this.fetchData()
}
previousPage = () => {
axios.get(`https:sample.sale/api/articles/ios_index${this.state.blogPages.pagination.previous_page}`)
.then(res => {
this.setState({
blogs: res.data.data,
blogPages: res.data.metadata
})
})
.catch(error => {
return (error);
});
}
nextPage = () => {
axios.get(`https:sample.sale/api/articles/ios_index${this.state.blogPages.pagination.next_page}`)
.then(res => {
this.setState({
blogs: res.data.data,
blogPages: res.data.metadata
})
})
.catch(error => {
return (error);
});
}
render() {
let feed = "Loading...";
if (this.state.blogs) {
feed = this.state.blogs.map((ele, idx) => {
return (
<div key={idx} >
<div className="articleContent">
<p><strong>{ele.franchise}</strong></p>
<h1 className="title"> {ele.title}</h1>
</div>
</div>
)
})
}
return (
<div>
<h3 FEED</h3>
{feed}
<button onClick={this.previousPage}>Previous Page</button>
<button onClick={this.nextPage}>Next Page</button>
</div>
)
}
}
At present you are building a strange URL for both the next and previous page functions:
axios.get(`https:sample.sale/api/articles/ios_index${this.state.blogPages.pagination.next_page}`)
// but this.state.blogPages.pagination.next_page is equal to "/api/articles/ios_index?page=2", right?
// So if we replace the variable with its value, your url actually looks something like this:
axios.get('https:sample.sale/api/articles/ios_index/api/articles/ios_index?page=2')
The correct call should look like:
axios.get(`https:sample.sale${this.state.blogPages.pagination.next_page}`)
And similarly for previous page.

Categories

Resources