Api route returning empty array - vuejs2

Api route returning empty array evenif table contains data.
I want to list the users.Route model binding fails
This is my api route
Route::middleware('auth:api')->get('/users',function(){
return App\User::get();
});
This is my vue component used in the blade template
<template>
<div class="row" style="min-height:250px;">
<ul>
<li v-for="user in users">
#{{user.name}}
</li>
</ul>
</div>
</template>
<script>
export default{
data() {
return {
users : [],
}
},
ready: function(){
this.getUsers();
},
methods: {
getUsers: function(response){
axios.get('http://localhost:8000/api/users')
.then(response => {
this.users = response.data;
})
.catch(error => {
});
},
},
}
</script>

Related

Losing my data when i refresh page in vuejs

I'm creating a social network for project in my formation, i have a like system and it work.
i have a components cardArticle with all info and i try to do a like count. It work but when i refresh the page or going on other page, i lost all my data likes (my data is not saved)
components/CardArticle.vue
<template>
<div id="card">
<div>
<a class="cardLink">
<img class="card-img" v-if="post.imageUrl !== undefined" :src="post.imageUrl" />
<h2 class="cardTitle"> {{ post.title }}</h2>
<p class="cardDescription"> {{ post.description }}</p>
</a>
</div>
<div class="buttonIcon">
<div>
<button type="button" class="buttonDelete" id="buttonDelete" #click="deletePost"
v-if="this.post.userId === this.user.userId || this.user.isAdmin === true">Supprimer</button>
<button type="button" class="buttonEdit" id="buttonEdit" #click="modifyPost"
v-if="this.post.userId === this.user.userId || this.user.isAdmin === true">
Editer
</button>
</div>
<div class="divIconLike">
<div class="iconLike">
<a #click="sendLike">
<i class="fa-regular fa-thumbs-up"></i>
</a>
</div>
<div class="countLike">
<p> {{ likes }} </p>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
import router from "../router/index.js";
export default {
name: 'CardArticle',
data () {
return {
likes: 0
}
},
props: {
post: {
type: Object
}
},
computed: {
user() {
return this.$store.getters.user;
}
},
methods: {
sendLike() {
axios.post("http://localhost:3000/api/articles/" + this.post._id + "/like", {
userId: this.user.userId
}, {
headers: {
Authorization: "Bearer " + this.user.token
}
})
.then(response => this.likes = response.data.article.likes)
.catch(error => console.log(error))
}
}
}
</script>
views/home.vue
<template>
<div class="home" v-if="this.user.token !== null">
<CardArticle v-for="post in allPosts" v-bind:key="post.id" :post="post" />
</div>
</template>
<script>
import CardArticle from "../components/CardArticle.vue"
import axios from "axios";
export default {
name: 'HomeArticle',
data () {
return {
post: {
title: "",
description: "",
imageUrl: ""
},
allPosts: [],
}
},
computed: {
user() {
return this.$store.getters.user;
}
},
components: {
CardArticle,
},
mounted() {
axios.get("http://localhost:3000/api/articles", {
headers: {
Authorization: "Bearer " + this.user.token
}
})
.then(response => {
this.allPosts = response.data;
})
.catch(error => {
return error;
})
}
}
</script>
What i should do for not losing my data ?
I would not use vuex or localstorage for that if possible, you have idea ?
Thanks for your help
If you loading data from server, then refresh page, you always will be lose data, because browser loading page again from server, and application will load data again.
If you don't want use vuex (but why not?), you can write data to cookies (by setting cookie value), then load it on app startup (when page is loaded). But it's not best practice at all. You can use vue3-cookies lib (link).
By the way, better learn to use stores, most progressive, I think, is Pinia.
Check: https://pinia.vuejs.org/
i lost all my data likes (my data is not saved)
likes is belong to each articles and It should have been saved to your db and call API to retrieve it again on component mounting:
export default {
name: 'CardArticle',
data () {
return {
likes: 0 // It's not managed by component state
}
},
methods: {
sendLike() {
axios.post("http://localhost:3000/api/articles/" + this.post._id + "/like", {
userId: this.user.userId
}, {
headers: {
Authorization: "Bearer " + this.user.token
}
})
.then(
// invalidates, update allPosts props (emit to parent)
)
.catch(error => console.log(error))
}
}
}

Why Vue doesn't refresh list using props?

On my App, on mounted() method, I call an API, which give to me a JSON with a list of items; than, I update the prop I've set in my target Homepage component:
Homepage.pages = resJSON.data.pages;
Here's the App code:
<template>
<div id="app">
<Homepage title="PWA Test"/>
</div>
</template>
<script>
import Homepage from './components/Homepage.vue'
export default {
name: 'App',
components: {
Homepage
},
mounted() {
let endpoint = "http://localhost:5000/api/graphql?query={pages(orderBy:{contentItemId:asc}){contentItemId,createdUtc,author,displayText,description%20}}";
fetch(endpoint, {
method:'GET',
headers: {
'Accept':'application/json',
'Content-Type':'application/json'
}
})
.then((response) => {
// check for HTTP failure
if (!response.ok) {
throw new Error("HTTP status " + response.status);
}
// read and parse the JSON
return response.json();
})
.then((res) => {
Homepage.pages = res.data.pages;
})
.catch((error) => {
console.log(error);
});
}
}
</script>
<style>
</style>
Here's the Homepage component:
<template>
<div id="homepage">
<h1>{{ title }}</h1>
<ul>
<li v-for="page in pages" :key="page.description">#{{ page.description }}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Homepage',
props: {
title: String,
pages: []
}
}
</script>
<style scoped>
</style>
But the ul doesn't update after receiving the JSON and updating the props pages. Where's my error?
you need to get the response.json(); in a data property of the App and then pass it down to the Homepage component. So your code should you look like this,
App code:
<template>
<div id="app">
//binding page into data property
<Homepage title="PWA Test" :pages="pages"/>
</div>
</template>
<script>
import Homepage from './components/Homepage.vue'
export default {
name: 'App',
data: function () {
return {
//data propety
pages : []
}
},
components: {
Homepage
},
mounted() {
let endpoint = "http://localhost:5000/api/graphql?query={pages(orderBy:{contentItemId:asc}){contentItemId,createdUtc,author,displayText,description%20}}";
fetch(endpoint, {
method:'GET',
headers: {
'Accept':'application/json',
'Content-Type':'application/json'
}
})
.then((response) => {
if (!response.ok) {
throw new Error("HTTP status " + response.status);
}
// assign the result to the data property
this.page = response.json();
})
.then((res) => {
Homepage.pages = res.data.pages;
})
.catch((error) => {
console.log(error);
});
}
}
</script>
Do you pass the props in a template after this.pages = res.data.pages?
<Homepage :pages="pages" />
I think there are some mistakes that you have done in your code, if you want change update prop value then you have to initialized your props values in script.
<template>
<div id="homepage">
<h1>{{ title }}</h1>
<ul>
<li v-for="page in currentPages" :key="page.description">#{{ page.description }}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Homepage',
props: {
title: String,
pages: []
}
data: function () {
return {
currentPages: this.pages
}
}
}
</script>
I hope this will help you to solve your issue- thanks!

Rendering component on runtime after Http request in VueJS

I'm trying to conditionally render a component in VueJS after an Http request right away when the application starts. If the response is ok I would like to render component 1, otherwise component 2. I would also like to render the component onClick
App.vue
<template>
<div id="app">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="navbar-collapse" id="navbarsExample05">
<ul class="navbar-nav pl-md-5 ml-auto">
<li v-for="tab in tabs" v-bind:key="tab" v-bind:class="['nav-item nav-link', { active: currentTab === tab }]"
v-on:click="currentTab = tab">
{{ tab }}
</li>
</ul>
</div>
</nav>
<component v-bind:is="currentTabComponent" class="tab"></component>
</div>
</template>
<script>
import Comp1 from '../components/comp1'
import Comp2 from '../components/comp2'
export default {
name: 'App',
components: {
Comp1,
Comp2
},
data: function() {
return {
currentTab: 'Comp2',
tabs: ['Comp1', 'Comp2']
};
},
computed:{
currentTabComponent: function () {
function check(){
fetch('someHttpUrl')
.then(response => response.json())
.then(data => {
resolve('Comp1')
});
.catch(err => {
resolve('Comp2')
})
}
var result = check();
result.then(async function (data) {
return data
})
}
}
}
</script>
When I click on the tab, the right component is loaded. But not when the application starts.
Is there any Vue method to render asynchronous a component?
There is no need to have currentTabComponent computed method.
You can just make your HTTP call and update currentTab when it is done.
Something like this:
mounted() {
fetch('someHttpUrl')
.then(response => response.json())
.then(data => {
this.currentTab = 'Comp1'
});
.catch(err => {
this.currentTab = 'Comp2'
})
}
I also removed the method named check as it seemed redundant.

VueJs + Firestore realtime listeners and update changes

I'am working with vuejs and firestore.I'am trynig to make my data change without refreshing page. the code below add me new line when i change the value on firestore.
value before changing:
value after changing:
my code:
{
<template>
<div id="dashboard">
<ul class="collection with-header">
<li class="collection-header"><h4>PLC</h4></li>
<li v-for="post in plc_value" v-bind:key="" class="collection-item">
<div class="chip">{{post.value_g}}</div>
<router-link class="secondary-content" v-bind:to="{ name: '', params:{} }"><i class="fa fa-eye"></i></router-link>
</li>
</ul>
</div>
</div>
</template>
<script>
import db from './firebaseInit';
export default {
name: 'dashboard',
data() {
return {
plc_value: [],
// loading: true
};
},
created() {
db
.collection('plc_value')
.onSnapshot(snap => {
snap.forEach(doc => {
const data = {
id: doc.id,
value_g: doc.data().value_g
};
this.plc_value.push(data);
});
});
}
};
</script>
}
In your created function, do this:
created() {
db
.collection('plc_value')
.onSnapshot(snapshot => {
const documents = snapshot.docs.map(doc => {
const data = {
id: doc.id,
value_g: doc.data()
}
return data
});
this.plc_value.push(documents);
});
});
}

Vue component not updated when props are async

I have this component
<template>
<div class="list-group">
<div v-for="user in data">
<!-- omitted for brevity -->
</div>
</div>
</template>
<script>
export default ("users-list", {
props: ['users']
,
data() {
return {
data: this.users
}
}
});
</script>
This component is used from another component witch get data with $.ajax (Promise) and set the data
<template>
<div>
<users-list v-bind:users="users"></users-list>
<div>
</template>
<script>
import UsersService from './users.service.js';
import UsersList from './users.list.vue';
export default ('users-main', {
components: {
'users-list': UsersList
},
mounted() {
this.refresh();
},
data() {
return {
data: null,
message: null,
user: null
}
},
methods: {
refresh() {
let service = new UsersService();
service.getAll()
.then((data) => {
this.data = data;
})
.catch((error) => {
this.message = error;
})
},
selected(user) {
this.user = user;
}
}
});
</script>
And this is the UsersService
import $ from 'jquery';
export default class UsersService {
getAll() {
var url = "/Api/Users/2017";
return new Promise((resolve, reject) => {
$.ajax({
url: url,
success(data) {
resolve(data);
},
error(jq, status, error){
reject(error);
}
});
});
}
}
As you can see the service get data with Promise, if I change
<div v-for="user in data">
into the property, I can see the users
<div v-for="user in users">
Question: How I can pass async props value to the components ?
You set data once "onInit" in users-list.
For reactivity you can do
computed:{
data(){ return this.users;}
}
or
watch: {
users(){
//do something
}
}
What do you mean by:
As you can see the service get data with Promise, if I change
<div v-for="user in data">
into the property, I can see the users
<div v-for="user in users">
Use <div v-for="user in users"> should work, so what's the problem?