diff --git a/packages/vue-router/src/types.ts b/packages/vue-router/src/types.ts
index 79700f08d9f..0be36407361 100644
--- a/packages/vue-router/src/types.ts
+++ b/packages/vue-router/src/types.ts
@@ -42,6 +42,7 @@ export interface ViewItem {
exact: boolean;
registerCallback?: () => void;
vueComponentRef: Ref;
+ params?: { [k: string]: any };
}
export interface ViewStacks {
diff --git a/packages/vue-router/src/viewStacks.ts b/packages/vue-router/src/viewStacks.ts
index 6c867329799..c7b8e54364f 100644
--- a/packages/vue-router/src/viewStacks.ts
+++ b/packages/vue-router/src/viewStacks.ts
@@ -88,7 +88,8 @@ export const createViewStacks = () => {
vueComponentRef: shallowRef(),
ionRoute: false,
mount: false,
- exact: routeInfo.pathname === matchedRoute.path
+ exact: routeInfo.pathname === matchedRoute.path,
+ params: routeInfo.params
};
}
diff --git a/packages/vue/src/components/IonRouterOutlet.ts b/packages/vue/src/components/IonRouterOutlet.ts
index f337152bc24..a996cf378cc 100644
--- a/packages/vue/src/components/IonRouterOutlet.ts
+++ b/packages/vue/src/components/IonRouterOutlet.ts
@@ -355,15 +355,36 @@ export const IonRouterOutlet = defineComponent({
{ ref: 'ionRouterOutlet' },
// TODO types
components && components.map((c: any) => {
+ let props = {
+ ref: c.vueComponentRef,
+ key: c.pathname,
+ isInOutlet: true,
+ registerIonPage: (ionPageEl: HTMLElement) => registerIonPage(c, ionPageEl)
+ }
+
+ /**
+ * IonRouterOutlet does not support named outlets.
+ */
+ if (c.matchedRoute?.props?.default) {
+ const matchedRoute = c.matchedRoute;
+ const routePropsOption = matchedRoute.props.default;
+ const routeProps = routePropsOption
+ ? routePropsOption === true
+ ? c.params
+ : typeof routePropsOption === 'function'
+ ? routePropsOption(matchedRoute)
+ : routePropsOption
+ : null
+
+ props = {
+ ...props,
+ ...routeProps
+ }
+ }
return h(
c.vueComponent,
- {
- ref: c.vueComponentRef,
- key: c.pathname,
- isInOutlet: true,
- registerIonPage: (ionPageEl: HTMLElement) => registerIonPage(c, ionPageEl)
- }
- )
+ props
+ );
})
)
}
diff --git a/packages/vue/test-app/tests/unit/routing.spec.ts b/packages/vue/test-app/tests/unit/routing.spec.ts
new file mode 100644
index 00000000000..ef3f80ffc02
--- /dev/null
+++ b/packages/vue/test-app/tests/unit/routing.spec.ts
@@ -0,0 +1,123 @@
+import { mount } from '@vue/test-utils';
+import { createRouter, createWebHistory } from '@ionic/vue-router';
+import { IonicVue, IonApp, IonRouterOutlet, IonPage, IonTabs, IonTabBar } from '@ionic/vue';
+
+const App = {
+ components: { IonApp, IonRouterOutlet },
+ template: '',
+}
+
+const BasePage = {
+ template: '',
+ components: { IonPage },
+}
+
+describe('Routing', () => {
+ it('should pass no props', async () => {
+ const Page1 = {
+ ...BasePage,
+ props: {
+ title: { type: String, default: 'Default Title' }
+ }
+ };
+
+ const router = createRouter({
+ history: createWebHistory(process.env.BASE_URL),
+ routes: [
+ { path: '/', component: Page1 }
+ ]
+ });
+
+ router.push('/');
+ await router.isReady();
+ const wrapper = mount(App, {
+ global: {
+ plugins: [router, IonicVue]
+ }
+ });
+
+ const cmp = wrapper.findComponent(Page1);
+ expect(cmp.props()).toEqual({ title: 'Default Title' });
+ });
+
+ it('should pass route props as an object', async () => {
+ const Page1 = {
+ ...BasePage,
+ props: {
+ title: { type: String, default: 'Default Title' }
+ }
+ };
+
+ const router = createRouter({
+ history: createWebHistory(process.env.BASE_URL),
+ routes: [
+ { path: '/', component: Page1, props: { title: 'Page 1 Title' } }
+ ]
+ });
+
+ router.push('/');
+ await router.isReady();
+ const wrapper = mount(App, {
+ global: {
+ plugins: [router, IonicVue]
+ }
+ });
+
+ const cmp = wrapper.findComponent(Page1);
+ expect(cmp.props()).toEqual({ title: 'Page 1 Title' });
+ });
+
+ it('should pass route props as a function', async () => {
+ const Page1 = {
+ ...BasePage,
+ props: {
+ title: { type: String, default: 'Default Title' }
+ }
+ };
+
+ const router = createRouter({
+ history: createWebHistory(process.env.BASE_URL),
+ routes: [
+ { path: '/myPath', component: Page1, props: function(route) { return { title: `${route.path} Title` } } }
+ ]
+ });
+
+ router.push('/myPath');
+ await router.isReady();
+ const wrapper = mount(App, {
+ global: {
+ plugins: [router, IonicVue]
+ }
+ });
+
+ const cmp = wrapper.findComponent(Page1);
+ expect(cmp.props()).toEqual({ title: '/myPath Title' });
+ });
+
+ it('should pass route params as props', async () => {
+ const Page1 = {
+ ...BasePage,
+ props: {
+ title: { type: String, default: 'Default Title' }
+ }
+ };
+
+ const router = createRouter({
+ history: createWebHistory(process.env.BASE_URL),
+ routes: [
+ { path: '/:title', component: Page1, props: true }
+ ]
+ });
+
+ router.push('/myPath');
+ await router.isReady();
+ const wrapper = mount(App, {
+ global: {
+ plugins: [router, IonicVue]
+ }
+ });
+
+ const cmp = wrapper.findComponent(Page1);
+ expect(cmp.props()).toEqual({ title: 'myPath' });
+ });
+});