Vue.js, pass data to component on another route - javascript

Simple task to pass data from one page to another made a real headache to newbie in Vue.js
Here is my router
I'm rendering a form on "/" page, which make an API request,
and I just want to pass data to another route page with another component
Is it so hard to do in Vue? It made a real headache for me today.
Get data from API, save & send to another component. How can I do it?

As Antony said, since you've already enabled props in router/index.js, you can pass parameters in router.push like this:
router.push({
name: 'events',
params: {
items: data
}
});
then you will be able to receive items as props in EventsDisplay.vue
export default {
name: 'eventsDisplay',
props: ['items'],
};

If you want to save it globally, you could use an event bus or a VueX store to contain it, then save and load it from this event bus or store when you need to access it.
If you want to pass it between those two components only, and only when accessing the second page from the first one, you can pass properties to the route argument as per this guide: https://router.vuejs.org/en/essentials/passing-props.html

Try using Vuex
In Source Component
this.$store.commit('changeDataState', this.$data);
this.$router.push({name: 'user-post-create'});
In Destination Component
created () {
console.log('state', this.$store);
this.$store.getters.Data;
}

Add props true in your vue router
{
path: "/pay-now",
name: "pay",
props: true,
component: () =>
import(/* webpackChunkName: "about" */ "../components/account/pay.vue"),
beforeEnter: AuthGuard,
},
After that pass props with router like that
this.$router.push({
name: "pay",
params: {
result:this.result,
}
});

Related

Getting data with dynamic routing

I have a catalog item, by clicking I generate a slug and insert it into the NuxtLink.
Now in the component I need to get a specific element from the array, but I don't have a slug in the array. With the help of id, I would be able to find the desired element. I don't provide any id to Nuxt routing.
If I can somehow get the id of the desired element, then how do I do it?
I think it would be a bad idea to record the id in the pinia store.
How do they act in such situations in general? I use nuxt 3.
<NuxtLink class="catalog-item" :to="`catalog/${slug}`"></NuxtLink>
You can use the params property to pass the id of the desired element as a route parameter.
<NuxtLink class="catalog-item" :to="`catalog/${slug}/${id}`"></NuxtLink>
Then, in the component that is rendered when the NuxtLink is clicked, you can access the id route parameter using the $route.params.id property.
mounted() {
const id = this.$route.params.id
// use the id to get the desired element from the array
}
I would prefer decoupling the router param through props in the Component. Official docs
props: {
id: {
type: Number,
required: true,
},
},
Then in router file you need to enable props:
const routes = [{ path: '/user/:id', component: User, props: true }]

How to pass props between routes in vue.js?

I want to send a variable as a prop from a route to another in vue.
I have a vue component, Champions, using a v-for and creating a new component called ChampionCard for each character in a JSON file, and binding the current champion each time.
In ChampionCard, I just show the name and image of the champion.
I want that, when clicking on a ChampionCard, you get redirected to another component called Champion with URL champions/:champion.
But I can't find a way to send the champion data between those 2 routes.
The Champions component :
<div class="champions">
<ChampionCard v-bind:champion="champion" v-for="champion in champions" :key="champion.key">
</ChampionCard>
</div>
The ChampionCard component :
<article #click="redirectTo(champion)" class="champion">
<img class="champion-icon" :src="champion.image" :alt="champion.name">
<h2 class="champion-name"> {{ champion.name }} </h2>
</article>
redirectTo(champion) {
this.$router.push({ name: 'champion', params: { champion: champion.key }})
}
The above code is working as I get redirected to champions/championName, but I don't have access to my champion variable. What would be the best way to send it as a prop in Champion component ?
Thanks :)
My alternative is: While redirecting to champions/:champion route, just send the id of the champion (such as champions/123).
When you are redirecting to this route, you can store champion object in a global place (say store). So that you can lookup with id (123) when you're mounting the route.
One step further, if you cannot find the object in the global store, you can initiate a remote call. So that your route will not be broken if 123 is not in the store. (User can go directly to that route if they save some bookmarks of that page etc.)
To keep your object in the global place, you have different alternatives:
Simple State Management (Simple/Basic implementation)
Using Vuex
I think you can achieve what you want doing something like this:
Declare a new route:
{
path: '/champion/:championKey',
name: 'Some name',
component: ChampionComponent,
}
Then, when redirecting to this new route:
redirectTo(champion) {
this.$router.push("/champion/" + champion.key)
}
Now you can access to the url param like this:
this.$route.params.championKey // as declared in router.js

Access input from dynamically loaded component in parent component in Vuejs

I've created a wizard-type flow in Vuejs using dynamically loaded components, where the Save button is in the parent component, and all of the text fields are in the loaded components. When the Save button is clicked, I need two things to happen:
1) The next component is loaded (currently working)
2) Get data from the text field(s) in the child component and write them to my Vuex store.
Here is the code for the parent component:
<template>
<div>
<component :is="selectedComponent"></component>
<span #click="changeComponent(selectedComponent)" class="action button save">Save</span>
</div>
</template>
<script>
import auth from '#/api//auth'
import Establishment from '#/onboarding/components/OnboardingEstablishment.vue'
import Account from '#/onboarding/components/OnboardingAccount.vue'
import Vendor from '#/onboarding/components/OnboardingVendors.vue'
import Location from '#/onboarding/components/OnboardingLocation.vue'
import Menu from '#/onboarding/components/OnboardingMenu.vue'
export default {
data () {
return {
accountName: '',
selectedComponent: 'account'
}
},
components: {
establishment: Establishment,
account: Account,
vendor: Vendor,
location: Location,
appMenu: Menu
},
methods: {
changeComponent (current) {
// Mapping object to map what the next component should be
// when changing the dynamic component.
const componentFlow = {
account: 'establishment',
establishment: 'location',
location: 'vendor',
vendor: 'appMenu'
}
// Get the name of the next component.
var nextComponent = componentFlow[current]
this.selectedComponent = nextComponent
// We also need to update Vuex with the value from the text field.
},
updateState () {
// Write the data from the element to the state.
}
},
mounted () {
// Get name of logged in user.
auth.getAccountDetails()
.then(response => {
this.accountName = response.data.email
})
}
}
</script>
And as an example, here is OnboardingAccount.vue, one of the dynamically loaded components:
<template>
<div>
<h1>Hey {{ accountEmail }}</h1>
<p>Let's start at the top.</p>
<p>What do you want to name your Account?</p>
<input :value="accountName" type="text" />
<p>Note: Your account name is the top level of your management. Additional teams or establishments can be added under this account name.</p>
</div>
</template>
<script>
import auth from '#/api/auth'
import Establishment from '#/onboarding/components/OnboardingEstablishment.vue'
import Account from '#/onboarding/components/OnboardingAccount.vue'
import Vendor from '#/onboarding/components/OnboardingVendors.vue'
import Location from '#/onboarding/components/OnboardingLocation.vue'
export default {
data () {
return {
accountEmail: '',
accountName: ''
}
},
components: {
establishment: Establishment,
account: Account,
vendor: Vendor,
location: Location
},
mounted () {
// Get name of logged in user.
auth.getAccountDetails()
.then(response => {
this.accountEmail = response.data.email
})
}
}
</script>
What I need to do is somehow be able to access the value from the OnboardingAccount component when I click on the Save button in the parent Onboarding component so that I can write the date to the Vuex store, either in my changeComponent method, or elsewhere. In looking at the debugger, I don't see that value anywhere. How can I do what I need to do?
I'd keep the state for every component in the parent component and pass them down as props, then on input events #change or #blur (or other) emit an event. This is is basically standard component communication, but since you're using dynamic components this gets a bit more tricky, in passing props and events.
To pass props to dynamic components somewhat cleanly you can use v-bind, but on a whole object instead of per variable/property, like here. The properties of this object can be objects containing props for each dynamic component, also this keeps the component tag clean. Then each dynamic child component can pick out the property from the props object that is meant for it, and use that data. For the event back from the children set a generic event on the component tag, name e.g. childEvent, to which each dynamic component would report a change of its state, as in it would return the changed props, which would update the state in the parent component. Saving should then be simple as all the data is in the parent component.
Side note:
You're using dynamic components well but you can bring it to the next level if you utilize webpack's dynamic imports along with it, then you won't need to manually import each one and declare them as components. Take a look at this article.

How to rework an Angular1 App to a VueJs app

So I'll get right to it :
I'm trying to remake an existing app that used Angular 1 , instead using VueJS 2.
Being unfamiliar to Angular1 I find it challenging to decide on a few things :
1.What are factories(probably services), where do I place/write manage them?
2.Okay I know angular is big on controllers, but I cannot seem to understand if I were to use Vue , what's the alternative to the controller, and where to hold the code.
So, basically what I've gotten so far is to use VueX for state management and I have moved some services there, however - I can't figure out for example if a certain service #requires 'NameOfOtherService' , does it mean it imports it like in NodeJS const NameOfOtherService = require ('insert/path/here'); ?
Basically the app gets data from an API and php scripts, for example :
In the angular 1 version in my appsettings, which is using an AppConfig module I have a pathFromScript(script) => {} // etc.
My question is , how do I manage EVERYTHING that's going on within one app like that translated to Vue?
Thank you in advance I know it's entirely a shot in the dark here.
Yours truly ,
As for Vue.Js, your angular controllers are methods. If you need to get some data from an API, you can use a method to call a Vuex action and either return the value back to the method or add it to your state, so it's available everywhere. This will look like the example below.
I guess your factories / services are managing API calls. I would place that inside Vuex with axios to make API calls.
Methods is the same as controllers in Angular. You create methods on the specific page. If you need a method to be resused multiple places, you can use mixins. Mixins extends the specific page by importing it. You can read about it here: https://v2.vuejs.org/v2/guide/mixins.html
page.vue
{{data}}
export default {
import { mapActions, mapGetters } from 'vuex'
...
computed: {
...mapGetters({
data: 'getData'
})
},
methods: {
...mapActions({
getServerData: 'getDataFromServer'
})
},
created () {
this.getServerData()
}
}
store.js (vuex)
import axios from 'axios'
state: {
data: null
},
getters: {
getData: state => {
return state.data
}
},
mutations: {
setDataFromServer: (state, payload) => {
state.data = payload
}
},
actions: {
getDataFromServer: ({ commit }) => {
return axios.get('https://website.com/api/data').then((response) => {
commit('setDataFromServer', response)
})
}
}
In this example the created is calling the vuex action to get the data from the server. When the server returns the value, it calls a mutation which sets the response in a state (data). The mapGetters which calls the getters in vuex, returns the data from state. It updates whenever the state changes.
Hope this makes sense

How can you pass data from a parent route to a child route in Vue.js nested routes?

I am trying to use nested routing in my Vue.js application. I have the routing working, however I cannot figure out how to pass data from a parent route down to a child route.
Basically, the parent route is going to retrieve an object that has properties. For each specific nested child route, I want to show one of the properties on that object.
For example, if I have the object below:
myDataObject : {name : "Foo" , profile : "Profile Data", posts : "Posts Data" }
I would like to pass the "profile" variable to the child route "/user/:id/profile". In the case of "/user/:id/posts", I would like to pass the "post" variable in.
I thought I could accomplish this using props, but I cannot find an example that fits with routing and what I tried does not seem to work.
Here is a link to a jsfiddle of what I am trying to do.
http://jsfiddle.net/90q4sucj/2/
This is definitely doable with props.
In parent component
<template>
...
<router-view :profile="myDataObject.profile" />
...
</template>
In child component
<script>
export default {
name: "child",
props: ["profile"]
...
Now, in your child component you may access the data by referring to this.$props.profile.
I am using this pattern with Vue 2.5.16. and Vue Router 3.0.1.
PS: A good option is to also use vuex for such scenarios.
See the answer below for the correct answer
! You can retrieve data by using services you create. In the example given I've updated to follow the "fetch data after navigation" sample shown in the docs. It has a userService that will handle getting the user's profile.
! const userService = {
findProfile(id) { return 'Profile Data'; }
};
! Then I updated the UserProfile component to get the profile when it's created and it watches the $route for changes.
! const UserProfile = {
data() { return { profile: null } },
template: 'Profile {{ $route.params.id }} {{ profile }}',
methods: {
setProfile: function () { this.profile = userService.findProfile(this.$route.params.id); }
},
created: function () { this.setProfile(); },
watch: { '$route': 'setProfile' }
}
! As for passing it through like props: [] I didn't see a way but that's probably a good thing because it could start getting pretty convoluted. Here you know explicitly where the user profile is coming from and don't need to follow a rabbit hole to figure it out.
! http://jsfiddle.net/90q4sucj/3/

Categories