I've been using Vue with a firebase database for my data I think where I'm going wrong is with the routing but I'm not 100% sure. what I've done so far is I've got a database with peoples profiles in it and I've use v-for to display all of these profiles out on the home page and now I'm trying to get it so that when you click on their individual profile you got to another page which will then fill the profile out according to a template using the id of the profile you've just clicked to fill in the page with that documents data.
What I know isn't happening is it isn't getting an id of a document because it should console log but it doesn't and it just displays the error message I made that it can't find the profile, as I said I'm pretty sure it is something that has to be done to the router, but I am not sure what to do and how to do it?
Here is the code below of the home page where you first see the profiles and select them.
<script>
import getPremium from "../Composables/getPremium.js";
import getStandard from "../Composables/getStandard.js";
import getBasic from "../Composables/getBasic.js";
const counter = useCounterStore();
const profile = useProfileStore();
const profileA = profilesbasic();
const {Premium, error, load} = getPremium();
load();
const {Standard, error2, load2} = getStandard();
load2();
const {Basic, error3, load3} = getBasic();
load3();
</script>
<template>
<div v-for =" Basics in Basic" :key="Basics.id" >
<router-link to="/Samplebasic">
<div class= "hover:scale-105 transition ease-in-out duration-300 bg-neutral-800 hover:bg-neutral-900 active:bg-neutral-900 text-neutral-400 font-bold rounded-xl">
<br>
<p>{{ Basics.name }}</p>
<img src="../assets/Sample pic.png" class="object-contain ml-6 w-60 h-80 transition ease-in-out duration-300">
<div class="grid grid-cols-2 grid-rows-fit text-left ml-6">
<p>Age:</p>
<p>{{ Basics.Age }}</p>
<p>Location:</p>
<p>{{ Basics.Location }}</p>
<p>Phone:</p>
<p>{{ Basics.Phone }}</p>
</div><br>
</div>
</router-link>
</div>
</template>
This is the JavaScript file that gets the documents from the database and is then imported to the home page.
import { projectFirestore } from "../Firebase/Config";
import { ref } from "vue"
const getBasic = () => {
const Basic = ref([])
const error3 = ref(null)
const load3 = async () => {
try{
const res = await projectFirestore.collection('Basic').get()
Basic.value = res.docs.map(doc => {
console.log(doc.data())
return {...doc.data(), id: doc.id}
})
}
catch (err){
error3.value = err.message
console.log(error3.value)
}
}
return { Basic, error3, load3}
}
export default getBasic
This is the profile page which I'm trying to get filled with the individuals' details depending on the profile you clicked on.
import getPBasic from "../Composables/getPBasic";
const {PBasic, error, load} = getPBasic();
load();
export default {
name: "Slider",
mounted(){
this.PBasic = PBasic;
this.error = error;
this.load = load;
},
data() {
return {
error: {},
PBasic: {},
load: {},
images: [
"/src/assets/sample-1.jpg",
"/src/assets/sample-2.jpg",
"/src/assets/sample-3.jpg",
"/src/assets/sample-4.jpg"
],
currentIndex: 0
};
},
methods: {
next: function() {
this.currentIndex += 1;
},
prev: function() {
this.currentIndex -= 1;
}
},
computed: {
currentImg: function() {
return this.images[Math.abs(this.currentIndex) % this.images.length];
}
}
};
</script>
<template>
<div v-if="error">{{ error }}</div>
<div v-if="PBasic" class="PBasic">
<br><br>
<p class="text-5xl text-red-700 font-serif">{{ PBasic.name }}</p><br><br>
<p>{{ Pbasic.age }}</p>
</template>
This is the javascript file that should get me that individual document based on the id of profile user clicked on.
import { projectFirestore } from "../Firebase/Config";
import { ref } from "vue"
const getPBasic = (id) => {
const PBasic = ref(null)
const error = ref(null)
const load = async () => {
try{
let res = await projectFirestore.collection('Basic').doc(id).get()
if(!res.exists) {
throw Error('That Profile no longer exists')
}
PBasic.value = {...res.data(), id: res.id}
console.log(PBasic.value)
}
catch (err){
error.value = err.message
console.log(error.value)
}
}
return { PBasic, error, load}
}
export default getPBasic
And this is the router of the sample basic as I have it now, I'm pretty sure it's the problem I just don't know how to fix it or what to do to the other files once I've done it?
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../components/Home.vue'
import Login from '../components/Login.vue'
import Advertise from '../components/Advertise.vue'
import Samplebasic from '../components/Samplebasic.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/Login',
name: 'Login',
component: Login,
},
{
path: '/Advertise',
name: 'Advertise',
component: Advertise,
}
{
path: '/Samplebasic',
name: 'Samplebasic',
component: Samplebasic,
}
]
const router = createRouter({
history: createWebHistory(),
routes,
})
export default router;
```
I hope I didn't go on for too long but that's the problem I'm having, and I don't know how to go about any help would be greatly appreciated, Thanks.
Related
I'm quite new with Vue and Vuex, actually I'm just doing a little app which display events, and you can access to each card event and see details through the card's ID. I passed all the code to vuex Store, and I'm having problems rendering individual cards, based on the error I understand that the problem is accessing the ID, but I'm console logging the props.id, and you can see the result in console:123 (I clicked on the first card and that's the correct ID)
So here's the EventList Component:
once I click on one of 'em, I get this console error:
Here is the code:
EventDetails component:
<template>
<div class="event-card">
<h2>You are on {{ $route.params.props.id }}</h2>
<span>#{{ event.time }} on {{ event.date }}</span>
<h4>{{ event.title }}</h4>
<p>{{ event.description }}</p>
</div>
</template>
<script>
import store from "#/store";
import { computed } from "#vue/reactivity";
import { onBeforeMount, onMounted, reactive, ref, toRefs } from "vue";
import { useStore } from "vuex";
export default {
name: "EventDetails",
props: ["id", "modelValue"],
setup(props) {
const state = reactive({
events: [],
event: {},
});
const message = ref("AsapRocky");
console.log(props.id)
onMounted(() => {
store.dispatch('fetchEvent', props.id)
});
const event = computed(() => {
return store.state.event;
});
return {
event,
message,
...toRefs(state),
};
},
};
</script>
store code:
import { createStore } from 'vuex'
import apiClient from '../services/EventService';
export default createStore({
state: {
user: 'TommyDemian',
events: [],
event: {}
},
mutations: {
SET_EVENTS(state, events){
state.events = events;
},
SET_EVENT(state, event) {
state.event = event;
}
},
actions: {
fetchEvents({ commit }){
apiClient
.getEvents()
.then((response) => {
commit("SET_EVENTS", response.data)
})
.catch((error) => {
console.log(error);
});
},
fetchEvent({ commit }, id){
apiClient.getEvent(id)
.then((response) => {
commit("SET_EVENT", response.data)
})
.catch((error) => {
console.log(error);
});
}
},
getters: {
},
modules: {
}
})
The stacktrace indicates the problematic reference to id is actually in {{ $route.params.props.id }} from your template.
I assume you were trying to access the component's id prop, which would not be in the route parameters:
<!-- <h2>You are on {{ $route.params.props.id }}</h2> --> ❌
<h2>You are on {{ id }}</h2> ✅
I'm new vuejs learner and I want to get the query value from url to use it in the vue method as explained below.
This is the route:
{
path: "/FetchData/:query?",
name: "FetchData",
component: FetchData,
}
And this is the link to redirect to the second page
<router-link :to="{ path: '/FetchData', query: { query: country.countryName }}">
this is the api
public IActionResult GetSubs(string query, int? subs)
{
return Ok(SubService.GetSubs(query, subsId));
}
This is the vue method calling the api
getSubs() {
axios.get("https://localhost:44391/api/Subs/GetSubs")
.then(res => this.subs = res.data)
.catch(err => console.log(err))
}
And finally, this is the html to display data
<div class="d-flex flex-row mb-3">
<div class="d-flex flex-column ml-2"><span>{{subs.subsId}}</span></div>
</div>
<h6 style="text-align:left">{{subs.label}}</h6>
if you're using vuejs 2 you can access query using: this.$route.query
but if you're using v3 it should be something like:
import { useRoute } from 'vue-router'
import { computed } from 'vue';
export default {
setup() {
const route = useRoute()
return {
query: computed( () => route.query )
}
}
}
then you can use this.query inside your method
So I'm building my first vue project and I've been trying to pass route parameters to an axios get request and it's not working.
this is the code for the page, it gets rendered after the user clicks on a dynamic link in a table of tests
<template>
<v-app>
<app-navbar />
<v-main>
<h3>test {{$route.params.name}}, {{$route.query.status}},{{$route.query.tag}}</h3>
<h3>{{items}}</h3>
</v-main>
</v-app>
</template>
<script>
import appNavbar from '../../../components/appNavbar.vue';
import axios from "axios";
export default {
components : {appNavbar},
name: "App",
data() {
return {
items: [],
};
},
async created() {
try {
const res = await axios.get(`http://localhost:3004/tests`,{ params: $route.params.name });
this.items = res.data;
} catch (error) {
console.log(error);
}
},
};
</script>
<style lang="scss" scoped>
</style>
how can i pass the route params to the axios get function ?
This should be this.$route.params.name inside the script.
const res = await axios.get(`http://localhost:3004/tests`,{ params: this.$route.params.name });
Router.js const routes = [ { path: 'path/:name', name: 'Name', component: ComponentName, } ]
I used #Nitheesh solution I just had to specify the parameter name and it worked perfectly
Solution:
const res = await axios.get(`http://localhost:3004/tests`,{ params: {name:this.$route.params.name} });
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)
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.