How to pass data to a router-view in Vue.js - vue.js

How can I pass data from my main app to a component through router-view in Vue.js? I have successfully gotten the data from my API as shown below:
mounted() {
// console.log(model)
this.model = model;
// console.log(this.model)
}
The component I want to pass data to has been loaded as shown below:
#section('content')
<div style="padding: 0.9rem" id="app">
<router-view name="bookBus"></router-view>
<router-view></router-view>
{{-- #{{ model }} --}}
</div>
#stop
How do I pass the model data to the bookBus component?

From https://router.vuejs.org/en/api/router-view.html
Any non-name props will be passed along to the rendered component, however most of the time the per-route data is contained in the route's params.
So if you want to pass data down from the parent component, rather than from the router, it would be something like this:
<router-view name="bookBus" :model="model"></router-view>
Your bookBus component would then need to have a model prop configured to receive the data, just like it would for any other prop.

Related

Is there a way to pass elements to a vue component?

when I need to pass some information between child and parent element I use props. But is there a way to pass elements to the component, for example like this
<MyComponent>
<router-link to="/oneOfTheList">OneOfTheList</router-link>
</MyComponent>
Router-Link seems to do it somehow...
How can I specify where the elements will be placed in my component
This is called slot
ComponentA.vue
<div>
<slot></slot>
</div>
ComponentB.vue
<component-a>
<span>test</span> // this part will be shown inside component A's slot tags
</component-a>
Here you go

How do I provide the component that is replacing <slot> with properties?

I have a component that functions as a basis for other components.
//The Basis Component lets call it slotComponent
<template>
<div>
//somestuff
<slot :someProperties="someLocalValues"></slot>
</div>
</template>
As you can see I want to give the component that is replacing the slot some Properties that only this component will know.
However if I do this:
//Some page Component lets call it mainPage
<template>
<slotComponent>
<someOtherComponent/>
</slotComponent>
</template>
Then "someOtherComponent" will not have access to "someProperties". How can I provide this component with said property?
Note that someLocalValues are defined in the scope of slotComponent and not its parent. So I cant provide said information in the mainPage.
You need to specify the v-slot directive in order to bind the props. Check the documentation here: https://v2.vuejs.org/v2/guide/components-slots.html#Scoped-Slots
You also will need to pass the props to your child component.
In your example, you would need to do something like:
<template>
<slotComponent>
<someOtherComponent v-slot="slotData" :data="slotData.someProperties"/>
</slotComponent>
</template>
This is the same, but with an additional <template> for clarity:
<template>
<slotComponent>
<template v-slot="slotData">
<someOtherComponent :data="slotData.someProperties"/>
</template>
</slotComponent>
</template>

How to update properties of component for dynamic router-link in vuejs

So new to Vue and haven't found anything that specifically addresses my issue.
I have a simple Vue app using VueRouter where I am trying to generate a bracket-style sports tournament that records the outcomes of the different games in the tournament.
I need to make an asynchronous axios call to a server to get info on a specific game. I do not know how to update my component properly to get this info.
App.vue is very simple. The home page is just an overview of the bracket
<template>
<div id="app">
<div id="nav">
<router-link :to="{ name: 'bracket'}">Bracket</router-link>
</div>
<router-view />
</div>
</template>
I have a view component, Bracket.vue, and, for now, all I want this view do is provide links to the different matchups in the tourney.
I have made this work pretty well dynamically as follows:
<template>
<div class="home">
<div id="nav">
<div v-for="round in rounds" :key="round">
<router-link v-for="game in gamesPerRound" :key="matchupKey(round, game)" :to="{ name: 'matchup', params: {round: round, game: game} }">Matchup {{ round }} {{ game }}</router-link>
</div>
</div>
</div>
</template>
When link is clicked, I pull up another view component, Matchup.vue, which I would like to display certain data about the matchup. (MatchupService is an axios API instance)
I pass the round # and the game # as props via router-link. These load fine in the Matchup.vue.
However, when I try to make an asynchronous call to get the matchup data, nothing happens. the matchup property never updates, not on the link click or ever. So I either get nothing (when I use a ternary as per below) or an error if I just try to use the matchup value
Matchup.vue
<template>
<div class="matchup">
<h1>Round {{ round }}</h1>
<h2>Game {{ game }}</h2>
<h6>Team 1: {{matchup.teams ? matchup.teams[0]: 0}}</h6>
<h6>Team 2: {{matchup.teams ? matchup.teams[1] : 0}}</h6>
</div>
</template>
<script>
import MatchupService from '#/services/MatchupService.js'
export default {
props: ["round", "game"],
data() {
return {
matchup: {},
}
},
async updated() {
let matchups = await MatchupService.getMatchups()
this.matchup = matchups.data.rounds[this.round].games[this.game]
},
}
</script>
I have tried many different approaches on this: updated vs. created vs. other hooks, I've tried to update a property post-load and hook that to v-if, etc.
I am just totally stymied on this so hoping for some help.
Looks like you need to use navigation hook beforeEnter in your router.js file or you can use beforeRouteEnter hook directly in your compoennt file. (NOTICE! Using beforeRouteEnter in a component file you can't access 'this', so maybe, there is a reason to use Vuex if you want to store some data within serfing your app). There you can define/fetch/set any data before redirect user to a specific page. By this way you do any actions you want and set it before redirecting.
More about you can find here:
https://router.vuejs.org/guide/advanced/navigation-guards.html

Single file component - re mount component on changing a value from navbar

This is the structure of my vuejs application.
<template>
<div class="page-body-wrapper">
<Sidebar/>
<div class="main-panel">
<Header/>
<div class="content-wrapper">
<router-view></router-view>
</div>
</div>
</div>
</template>
<script>
import Header from '../header/header';
import Sidebar from '../sidebar/sidebar';
export default {
name: 'Layout',
components: {
Header,
Sidebar
}
}
</script>
In all the routes that are rendered inside <router-view>, i am calling various functions and api calls based on a store variable 'myValue'. And, I have a dropdown in my <Header/> component ( which is common for all routes). Whenever I select a value from the dropdown in header, the store variable 'myValue' changes. Now, I need to remount whatever component is rendered inside <router-view> whenever the store variable 'myValue' changes. Using watch will be a last option since I will have to do the same in a number of components. I cannot use computed, since I have to fetch all data in either 'created' or 'mounted' hook. Is there any option to remount the entire <router-view> when a store variable changes? Note: I am using vuex for state management.
Just pass a key to <router-view :key="myValue"></router-view>, or in your case <router-view :key="$store.state.myValue"></router-view>.
Also check out this answer.

VUE same component instance at difference route

I am design an Vuejs app which page render based on route.
e.g. for
route = /, Component = Main.vue
<template>
<div>
<toolbar :user="user"></toolbar>
<app-content></app-content>
</div>
</template>
route = /:user, Component = User.vue
<template>
<div>
<toolbar :user="user"></toolbar>
<userHeader></userHeader>
<app-content></app-content>
</div>
</template>
When the page is show, the toolbar component will fetch data from server, the problem is, when the page go from / to /user, the data fetching data X 2 because that are 2 toolbar components in the app itself.
How should resolve this issue ? is that any way to reuse share component instances like toolbar ?
or should i put the design in one whole component instead ? ( use v-if to show hide the additional component)
You should be having <toolbar /> outside of <router-view></router-view>.
So your code should look like:
<div id="app">
<toolbar user="user" />
<router-view />
</div>
With this <toolbar /> won't change even if you change your routes, and will result in data fetching for a single time only.