Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<router-view> add matchedRoute as v-slot param #1407

Closed
yurks opened this issue May 18, 2022 · 7 comments
Closed

<router-view> add matchedRoute as v-slot param #1407

yurks opened this issue May 18, 2022 · 7 comments

Comments

@yurks
Copy link

yurks commented May 18, 2022

What problem does this feature solve?

In case we have nested routers it's needed to get matched route object for every view. While children route is active, there is no official way to know what exactly matched as parent route, only it's component:

<router-view v-slot="{ Component, route, matchedRoute }">
  {{ matchedRoute.name }}
  <component :is="Component" />
  <router-view/>
</router-view>

What does the proposed API look like?

matchedRoute param passed with v-slot in <router-view>

@yurks
Copy link
Author

yurks commented May 18, 2022

A workaround for those who need it "right now":

<script setup lang="ts">
import type { VNode } from 'vue'
import { useRouter } from 'vue-router'

const normalizedRoutes = getRoutes()
const getMatchedRoute = (component: VNode) =>
  component &&
  normalizedRoutes.find(({ components }) => components.default === component.type)
</script>
<template>
<router-view v-slot="{ Component }">
  <h3>{{ getMatchedRoute(Component)?.meta.title }}</h3>
  <component :is="Component"></component>
  <router-view></router-view>
</router-view>
</template>

@posva
Copy link
Member

posva commented May 18, 2022

The information that you can get is the matched route record but there isn't a matched route per nested route, there is always one single matched route and this is intentional.

To access the matched route record anywhere you need to index the route.matched array with the depth of the current view. Usually, you know this information within the component but since it's not always the case, you can inject the depth of the current view with viewDepthKey (https://github.com/vuejs/router/blob/main/src/index.ts#L29) with something like:

import { viewDepthKey } from 'vue-router'

// within the setup of a component
const depth = inject(viewDepthKey)!
const route = useRoute()

// this could be a computed
route.matched[depth]

Accessing the route records is quite advanced functionality so I would be against exposing them easily to avoid confusion among users. As shown, it's still available for advanced use cases though. Do you have any use case that cannot be achieved with the example above?

There is also #1217 (comment).

@yurks
Copy link
Author

yurks commented May 18, 2022

Ok, index the roure.matched looks more accurate way to get it, thank you. But this could be done within route component only, not inside <router-view> like it used in template provided.
So, why not pass viewDepth with v-slot? Doesn't it make sense, as this could be used for accessing meta once and not duplicate that injects for every route component?

@posva
Copy link
Member

posva commented May 19, 2022

The depth is a low-level API, it would be confusing to expose it. Is there anything worth accessing this way besides meta? I think this should go through an RFC (you can open it) to see other peoples use cases.

@yurks
Copy link
Author

yurks commented May 19, 2022

I'm surprised with RFC recommendation for so trivial use case, I just trying to resolve an issue which exists (right now, and makes life harder). Don't really understand why you going to resolve a ghost-issue that could happen (somewhere somebody sometimes can feel confused).

@posva
Copy link
Member

posva commented May 19, 2022

It's okay if you don't want to do an RFC. To me, it's important to add APIs that are not possible otherwise, solve common problems, and cater to a good amount of use cases (not just one). The RFC allows finding that balance. It also allows checking for possible edge cases as I mentioned above.

Closing this in favor of #1408

@posva posva closed this as completed May 19, 2022
@yurks
Copy link
Author

yurks commented May 19, 2022

Thank you for your time.

For now this workaround doesn't works as depth must be reduced by 1 while accessing matched routes array: route.matched[depth-1].

But simpler solution seems to be inject(matchedRouteKey) which returns exactly what I need:

import { inject } from 'vue'
import { matchedRouteKey} from 'vue-router'

const matchedRoute = inject(matchedRouteKey)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants