]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
fix(matcher): merge params
authorEduardo San Martin Morote <posva13@gmail.com>
Wed, 22 Apr 2020 21:20:01 +0000 (23:20 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Wed, 22 Apr 2020 21:20:01 +0000 (23:20 +0200)
Fix #189

__tests__/matcher/resolve.spec.ts
src/matcher/index.ts

index 49fe6c8fbdcecb164adbe5a743e91990edccb540..b292abf8a4a2be927eeeba2332bb87ae3568b399 100644 (file)
@@ -723,6 +723,36 @@ describe('RouterMatcher.resolve', () => {
         assertErrorMatch({ path: '/', components }, { name: 'Home' })
       ).toMatchSnapshot()
     })
+
+    it('merges params', () => {
+      assertRecordMatch(
+        { path: '/:a/:b', name: 'p', components },
+        { name: 'p', params: { b: 'b' } },
+        { name: 'p', path: '/a/b', params: { a: 'a', b: 'b' } },
+        {
+          params: { a: 'a' },
+          path: '/a',
+          matched: [],
+          meta: {},
+          name: undefined,
+        }
+      )
+    })
+
+    it('only keep existing params', () => {
+      assertRecordMatch(
+        { path: '/:a/:b', name: 'p', components },
+        { name: 'p', params: { b: 'b' } },
+        { name: 'p', path: '/a/b', params: { a: 'a', b: 'b' } },
+        {
+          params: { a: 'a', c: 'c' },
+          path: '/a',
+          matched: [],
+          meta: {},
+          name: undefined,
+        }
+      )
+    })
   })
 
   describe('LocationAsRelative', () => {
@@ -822,6 +852,21 @@ describe('RouterMatcher.resolve', () => {
       )
     })
 
+    it('merges params', () => {
+      assertRecordMatch(
+        { path: '/:a/:b?', name: 'p', components },
+        { params: { b: 'b' } },
+        { name: 'p', path: '/a/b', params: { a: 'a', b: 'b' } },
+        {
+          name: 'p',
+          params: { a: 'a' },
+          path: '/a',
+          matched: [],
+          meta: {},
+        }
+      )
+    })
+
     it('throws if the current named route does not exists', () => {
       const record = { path: '/', components }
       const start = {
index fc50f5844943d2329329d93a67a26b8640c030d8..0c01858471e12518acf55211c95824bffeca5e05 100644 (file)
@@ -198,9 +198,13 @@ export function createRouterMatcher(
         })
 
       name = matcher.record.name
-      // TODO: merge params with current location. Should this be done by name. I think there should be some kind of relationship between the records like children of a parent should keep parent props but not the rest
-      // needs an RFC if breaking change
-      params = location.params || currentLocation.params
+      params = {
+        ...paramsFromLocation(
+          currentLocation.params,
+          matcher.keys.map(k => k.name)
+        ),
+        ...location.params,
+      }
       // throws if cannot be stringified
       path = matcher.stringify(params)
     } else if ('path' in location) {
@@ -227,7 +231,9 @@ export function createRouterMatcher(
           currentLocation,
         })
       name = matcher.record.name
-      params = location.params || currentLocation.params
+      // since we are navigating to the same location, we don't need to pick the
+      // params like when `name` is provided
+      params = { ...currentLocation.params, ...location.params }
       path = matcher.stringify(params)
     }
 
@@ -256,6 +262,19 @@ export function createRouterMatcher(
   return { addRoute, resolve, removeRoute, getRoutes, getRecordMatcher }
 }
 
+function paramsFromLocation(
+  params: MatcherLocation['params'],
+  keys: string[]
+): MatcherLocation['params'] {
+  let newParams = {} as MatcherLocation['params']
+
+  for (let key of keys) {
+    if (key in params) newParams[key] = params[key]
+  }
+
+  return newParams
+}
+
 /**
  * Normalizes a RouteRecordRaw. Transforms the `redirect` option into a `beforeEnter`
  * @param record