I'm trying to use vue-async-data to fetch data asynchronously before rendering my Vue component, but I'm having no success. I'm not getting any erros, but it simply doesn't work.
Here's my main.js code:
import Vue from 'vue'
import VueAsyncData from 'vue-async-data'
import router from './router'
import App from './App.vue'
Vue.use(VueAsyncData)
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
And here's my App.vue code:
<template>
<div>
{{ msg }}
<navigation wait-for="async-data"></navigation>
</div>
</template>
<script>
import Navigation from './components/Navigation.vue'
export default {
name: 'app',
components: {
Navigation
},
data: function() {
return {
msg: 'not loaded yet...'
}
},
asyncData: function (resolve, reject) {
// load data and call resolve(data)
// or call reject(reason) if something goes wrong
setTimeout(function () {
// this will call `vm.$set('msg', 'hi')` for you
resolve({
msg: 'hi'
})
}, 1000)
}
}
</script>
The msg value doesn't change at any moment, but the component is still rendered.
Am I missing somenthing?
As Bert Evans stated, vue-async-data doesn't work with Vue 2.0.
I used vue-router and the created function to achieve what I needed (as suggested in: https://router.vuejs.org/en/advanced/data-fetching.html.
<template>
<div>
<div class="loading" v-if="loading">
Loading...
</div>
<div v-if="error" class="error">
{{ error }}
</div>
<navigation v-if="currentUser"></navigation>
</div>
</template>
<script>
import Navigation from './components/Navigation.vue'
export default {
name: 'app',
components: {
Navigation
},
data: function() {
return {
loading: true,
error: false,
currentUser: null
}
},
created: function() {
this.fetchUserData()
},
methods: {
fetchUserData: function() {
this.$http.get('/Account/CurrentUserInfo').then(data => {
this.currentUser = data
this.loading = false
}, response => {
this.loading = false
this.error = true
});
}
}
}
</script>
Related
When I refresh my browser few times when I am on "ActorDetails.vue" page/component, not often but sometimes, I lost my actorsData prop data(should have array of 5 objects but become empty array), at first, I thought it's an API's problem but when I try to console.log() the data inside of "App.js", the data exist... I can't seem to find where the problem is.(Also I did try refresh the browser few times when I am on "ActorsList.vue" page/component, the prop data always exist)
Both pages/components("ActorList.vue" and "ActorDetails.vue") gets topActors data from "App.vue".
(Comments in code)
App.vue
<template>
<div id="app">
<router-view name="homePage" />
<router-view :actorsData="topActors" /> <== "ActorList.vue" and "ActorDetails.vue" use this "router-view"
<div class="over-limit-resolution">Over 4k</div>
</div>
</template>
<script>
import { getActors } from "./util/TheMoveDatabase";
export default {
name: "App",
data() {
return {
topActors: [],
};
},
created() {
getActors.then((result) => {
console.log(result); <== Data always came back from API even when my "actorsData" prop inside of "ActorsDetails.vue" lost it's data.
this.topActors = result;
});
},
methods: {},
};
</script>
ActorsList.vue
<template>
<div class="actors-list">
<router-link to="/">Home</router-link>
<div class="actors-list-container" v-if="allFiveActors">
<div
class="actor-container"
v-for="actorData in actorsData"
:key="actorData.id"
>
<router-link :to="'/actorslist/' + actorData.id">
<h3>{{ actorData.name }} | {{ actorData.id }}</h3>
</router-link>
</div>
</div>
</div>
</template>
<script>
export default {
name: "ActorsList",
props: ["actorsData"],
data() {
return {};
},
computed: {
allFiveActors() {
return this.actorsData.length > 0;
},
},
created() {
console.log(this.actorsData); <== Also tried to refresh the browser when I am on this page/component, prop data always exist.
},
};
ActorsDetails.vue (Page/Component that lost prop data)
<template>
<div class="actor-details">
<router-link to="/actorslist">Actors List</router-link>
<h1>Details page</h1>
<div class="actor-details-container" v-if="actorDetails">
<div class="actor-detail-info">
<h3>{{ actorDetails.name }}</h3>
<p>Birthday: {{ actorDetails.birthday }}</p>
</div>
</div>
</div>
</template>
<script>
import { getActorDetails } from "../util/TheMoveDatabase";
export default {
name: "ActorDetails",
props: ["actorsData", "actorId"],
data() {
return {
actorDetails: {},
};
},
methods: {
checkCurrentActorExist() {
const currentActor = this.getCurrentActor;
// console.log(currentActor);
if (!currentActor) {
// this.$router.push("/");
console.log("does not exist");
}
},
getActor() {
const currentActor = this.getCurrentActor;
console.log(currentActor);
console.log("RAN");
if (currentActor) {
getActorDetails(this.actorId).then((result) => {
this.actorDetails = result;
console.log(this.actorDetails);
});
}
},
},
created() {
this.checkCurrentActorExist();
this.getActor();
console.log(this.actorsData); <== When I am on this page/component and refresh the browser few times, sometimes my "actorsData" prop data is lost.
console.log(this.actorId);
},
computed: {
getCurrentActor() {
return this.actorsData.find(
(actor) => actor.id === parseInt(this.actorId)
);
},
},
};
</script>
Routes.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '../views/Home.vue';
Vue.use(VueRouter);
const routes = [
{
path: '/',
name: 'Home',
components: {
homePage: Home,
},
},
{
path: '/actorslist',
name: 'ActorsList',
component: () => import('../views/ActorsList.vue'),
},
{
path: '/actorslist/:actorId',
name: 'ActorDetails',
component: () => import('../views/ActorDetails.vue'),
props(route) {
// console.log(route);
return {
actorId: route.params.actorId,
};
},
},
];
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes,
});
export default router;
Just a guess, but maybe your loading-method sometimes takes to much time and the empty array already has been passed to the component.
I would try to clear the array and re-fill it with the loaded data instead of creating a new array (I would try to empty it using splice or pop and then refill it with push)
everyone. Sorry, for my dumb question, but I've tried a lot to do.
What I want to do is pass result of getUser() function to my Home.vue app.
But first, I tried to pass simple variable 'counter' using props:
main.js
import Vue from 'vue';
import App from './App';
import router from './router';
import store from './store';
Vue.config.productionTip = false;
export default new Vue({
router,
store,
el: '#app',
props: { 'counter': 1 },
template: '<app v-bind:counter="counter" />',
components: { App },
created () {
// fetch the data when the view is created and the data is
// already being observed
this.getUser()
},
methods: {
getUser() {
fetch('/api/auth/user/user/')
.then(response => response.json())
.then(data => console.log(data));
}
},
});
Home.vue
<template lang="pug">
#app
.card(v-for="profile in profiles")
.card-header
button.btn.btn-clear.float-right(#click="deleteProfile(profile)")
.card-title {{ profile.user }}
.card-body {{ profile.phone_number }}
.card-body {{ profile.address }}
.card-body {{ counter }}
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'profile-list',
computed: mapGetters(['profiles']),
props: ['counter'],
methods: {
deleteProfile (profile) {
// Вызываем действие `deleteNote` из нашего хранилища, которое
// попытается удалить заметку из нашех базы данных, отправив запрос к API
this.$store.dispatch('deleteProfile', profile)
}
},
beforeMount () {
// Перед тем как загрузить страницу, нам нужно получить список всех
// имеющихся заметок. Для этого мы вызываем действие `getNotes` из
// нашего хранилища
this.$store.dispatch('getProfile')
},
}
What I want to do is print 'counter' under profile.address but this doesn't work.
Thank you.
I don't see any initialisation of counter. Just change your code from
props: { 'counter': 1 } to
data () {return { 'counter': 1 }}
Learn more: https://v3.vuejs.org/api/options-data.html#data
HelloWorld.vue
import axios from "axios";
export const router = () => axios.get("https://fakestoreapi.com/products");
<template>
<div>
<div v-for="item in items" :key="item.id">
<b> id: {{ item.id }}</b>
<router-link
:to="`/${item.id}`"
>
{{ item.title }}
</router-link>
</div><!-- end v-for -->
<router-view></router-view>
</div>
</template>
<script>
import { router } from "./router";
export default {
name: "HelloWorld",
components: {},
data() {
return {
items: [],
};
},
mounted() {
router().then((r) => {
this.items = r.data;
});
},
};
</script>
User.vue
import axios from "axios";
export const routerid = (itemId) =>
axios.get("https://fakestoreapi.com/products/" + itemId);
<template>
<div>
<div v-if="item">
<h1>Price: {{ item.price }}</h1>
</div>
<tabs />
</div>
</template>
<script>
import { routerid } from "./routerid";
import tabs from "./tabs";
export default {
name: "User",
components: {
tabs,
},
data() {
return {
item: null,
};
},
mounted() {
this.loadData();
},
computed: {
routeId() {
return this.$route.params.id;
},
},
watch: {
routeId() {
console.log("Reload (route change)");
this.loadData();
}, //reload when route id changes
},
methods: {
loadData() {
console.log("Reloading, ID", this.routeId);
if (!this.routeId) return; // no ID, leave early
routerid(this.$route.params.id).then((item) => {
this.item = item.data;
});
},
},
};
</script>
tabs.vue
import axios from "axios";
export const tabsandcontent = async (itemId) =>
await axios.get("https://fakestoreapi.com/products?limit=" + itemId);
<template>
<div>
<div v-if="item">
<h1>description: {{ item.description }}</h1>
</div>
</div>
</template>
<script>
import { tabsandcontent } from "./tabsandcontent";
export default {
name: "User",
components: {},
data() {
return {
item: null,
};
},
mounted() {
this.loadData();
},
computed: {
tabsandcontent() {
return this.$route.params.id;
},
},
watch: {
tabsandcontent() {
console.log("Reload (route change)");
this.loadData();
}, //reload when route id changes
},
methods: {
loadData() {
console.log("Reloading, ID", this.tabsandcontent);
if (!this.tabsandcontent) return; // no ID, leave early
tabsandcontent(this.$route.params.id).then((item) => {
this.item = item.data;
});
},
},
};
</script>
main.js
import Vue from "vue";
import App from "./App.vue";
import VueRouter from "vue-router";
import HelloWorld from "./components/HelloWorld";
import User from "./components/User";
Vue.use(VueRouter);
const router = new VueRouter({
routes: [
{
path: "/HelloWorld",
name: "HelloWorld",
component: HelloWorld,
children: [{ path: ":id", name: "User", component: User }]
}
]
});
Vue.config.productionTip = false;
new Vue({
router,
render: (h) => h(App)
}).$mount("#app");
code:- https://codesandbox.io/s/combined-logic-api-forked-41lh0f?file=/src/main.js
can you please answer this, In main.js routing I changed from path: "/" to path: "/HelloWorld" then all of sudden output not reflecting... because in my project path:'/' indicates login page??? In this scenario what changes, i need to make, to make logic work
also where is the relation between path:'/' and api call??
You have same name for the variables in tabs component (In watch and computed). And In tabsandcontent.js, you have missed to fetch description for the specific item as performed in routerId.js.
Have a look at modified version which is working as you expected.
https://codesandbox.io/embed/combined-logic-api-forked-ji5oh4?fontsize=14&hidenavigation=1&theme=dark
First thing first, I want you to know that I don't understand what are you asking for. But I'm going to try to answer.
Your first question:
In main.js routing I changed from path: "/" to path: "/HelloWorld" then all of sudden output not reflecting.
Yes, you will not see your HelloWorld.vue component. You can see your page however if you type <your-url>/HelloWorld. Usually the / path is used for something like "Home" page.
However, I've tried checking out your codesandbox. And take a look at your HelloWorld.vue component.
I think you are confused because when you changed the path from / to /HelloWorld apart from the HelloWorld.vue not showing up. It somehow broken the link which causes the API in tabs.vue not functioning.
If that's the case, you just have to simply add HelloWorld/${item.id} in tabs.vue,
<template>
<div>
<div v-for="item in items" :key="item.id">
<b> id: {{ item.id }}</b>
<router-link
:to="`HelloWorld/${item.id}`" // --> Notice this line
>
{{ item.title }}
</router-link>
</div><!-- end v-for -->
<router-view></router-view>
</div>
</template>
This however, isn't a common thing to do routing. You should add your App URLs to main.js. Which also isn't common, but I'm assuming this is just a little reproduction code you made for StackOverflow.
Here are my CodeSandbox edits.
https://codesandbox.io/s/combined-logic-api-forked-jttt8p
I will update the answer again later, I'm still not on my personal laptop.
Similar to this question here I'm trying to pass socket.io-client data to a Vue.js component but it's not displaying on the page -- though it writes to console.log just fine. My data is JSON (his was an array) so the solution in the link above doesn't seem to work.
The error I'm getting is:
[Vue warn]: Property or method "items" is not defined on the instance but referenced during render.
main.js
import Vue from 'vue'
import App from './App'
import io from 'socket.io-client'
Vue.config.productionTip = false
var socket = io.connect('http://localhost:3000')
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>',
data: {
items: []
},
mounted: function () {
socket.on('connect', function () {
socket.on('message', function (message) {
console.log(message)
this.items = message.content
}.bind(this))
socket.emit('subscribe', 'mu')
})
}
})
App.vue
<template>
<div id="app">
<h1>client</h1>
<div v-for="item in items" class="card">
<div class="card-block">
<h4 class="card-title">Symbol: {{ item.symbol }}</h4>
<p class="card-text">Updated: {{ item.lastUpdated }}</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
sample data
{
"symbol":"MU",
"lastUpdated":1520283600000
}
Any help would be greatly appreciated. Thanks.
the data attribute in your vue instance needs to be a function which returns something, your items array for instance. so instead of
data: {
items: []
},
you should re-write as
data () {
return {
items: []
}
},
I installed Vue via npm and wanted to use it. Now when I load my page I get an error:
Uncaught SyntaxError: Unexpected token import in main.js:1
It worked when I put it the link to vue CDN in my HTML code, but now that I installed via NPM I receive this error.
Update
I find it strange that it does not work with any import at all. Even my custom components. As soon as I use the import statement, I get this error.
The Vue File:
import Vue from 'vue';
import axios from 'axios';
import Form from './core/Form';
window.Vue = Vue;
window.axios = axios;
window.Form = Form;
window.Event = new class {
constructor() {
this.vue = new Vue();
}
fire(event, data = null) {
this.vue.$emit(event, data);
}
listen(event, callback) {
this.vue.$on(event, callback);
}
};
Vue.component('panel', {
template: `
<div :class="panelType">
<div class="panel-heading">
<slot name="header"></slot>
</div>
<div class="panel-body">
<slot></slot>
</div>
</div>
`,
props: {
name: { required: true }
},
computed: {
panelType: function() {
switch(this.name) {
case 'default': return 'panel panel-default';
case 'primary': return 'panel panel-primary';
}
}
}
});
Vue.component('tabs', {
template: `
<div>
<div class="tabs-container">
<ul class="nav nav-tabs">
<li v-for="tab in tabs" :class="{'tab-pane active': tab.isActive }">
<a :href="tab.href" #click="selectTab(tab)">{{ tab.name }}</a>
</li>
</ul>
<div class="tab-content">
<slot></slot>
</div>
</div>
`,
data() {
return { tabs: [] };
},
created() {
this.tabs = this.$children;
},
methods: {
selectTab(selectedTab) {
this.tabs.forEach(tab => {
tab.isActive = (tab.name == selectedTab.name);
})
}
}
});
Vue.component('tab', {
template: `
<div v-show="isActive"><slot></slot></div>
`,
props: {
name: { required: true },
selected: { default: false }
},
data() {
return {
isActive: false
}
},
mounted() {
this.isActive = this.selected;
}
});
var app = new Vue({
el: '#app',
components: {
Example
},
data: {
form: new Form({
incidentReference: '',
streetName: '',
latitude: '',
longitude: '',
featureTypeId: 1,
archived: 0,
}),
incidents: []
},
computed: {
href() {
return '#' + this.name.toLowerCase().replace(/ /g, '-');
}
},
mounted: function () {
this.getIncidents();
},
methods: {
onSubmit() {
this.form.post('/api/v1/incidents');
},
getIncidents: function() {
console.log('getIncidents');
var self = this;
axios.get('/api/v1/incidents').then(function(response) {
// set data on vm
console.log(response.data);
var incidentsReceived = response.data.data.map(function (incident) {
return incident;
});
Vue.set(self, 'incidents', incidentsReceived);
});
}
}
});
Is it because you are using window.vue = vue;
rather than
window.Vue = vue;
OR
window.Vue = require('vue');