expect(spy).toHaveBeenCalledTimes(1)
})
+ it('casts number params to string', async () => {
+ const { router } = await newRouter()
+ await router.push({ name: 'Param', params: { p: 0 } })
+ expect(router.currentRoute.value).toMatchObject({ params: { p: '0' } })
+ })
+
it('navigates to same route record but different query', async () => {
const { router } = await newRouter()
await router.push('/?q=1')
* @param text - string to encode
* @returns encoded string
*/
-export function encodePath(text: string): string {
+export function encodePath(text: string | number): string {
return commonEncode(text).replace(HASH_RE, '%23').replace(IM_RE, '%3F')
}
* @param text - string to encode
* @returns encoded string
*/
-export function encodeParam(text: string): string {
+export function encodeParam(text: string | number): string {
return encodePath(text).replace(SLASH_RE, '%2F')
}
* @param text - string to decode
* @returns decoded string
*/
-export function decode(text: string): string {
+export function decode(text: string | number): string {
try {
- return decodeURIComponent(text)
+ return decodeURIComponent('' + text)
} catch (err) {
__DEV__ && warn(`Error decoding "${text}". Using original value`)
}
- return text
+ return '' + text
}
PostNavigationGuard,
START_LOCATION_NORMALIZED,
Lazy,
- MatcherLocation,
RouteLocationNormalizedLoaded,
RouteLocation,
RouteRecordName,
isRouteName,
NavigationGuardWithThis,
RouteLocationOptions,
+ MatcherLocationRaw,
} from './types'
import { RouterHistory, HistoryState } from './history/common'
import {
history.scrollRestoration = 'manual'
}
+ const normalizeParams = applyToParams.bind(
+ null,
+ paramValue => '' + paramValue
+ )
const encodeParams = applyToParams.bind(null, encodeParam)
const decodeParams = applyToParams.bind(null, decode)
}
}
+ let matcherLocation: MatcherLocationRaw
+
// path could be relative in object as well
if ('path' in rawLocation) {
if (
}" was passed with params but they will be ignored. Use a named route alongside params instead.`
)
}
- rawLocation = {
+ matcherLocation = {
...rawLocation,
path: parseURL(parseQuery, rawLocation.path, currentLocation.path).path,
}
+ } else {
+ matcherLocation = {
+ ...rawLocation,
+ params: encodeParams(rawLocation.params),
+ }
}
- let matchedRoute: MatcherLocation = // relative or named location, path is ignored
- // for same reason TS thinks rawLocation.params can be undefined
- matcher.resolve(
- 'params' in rawLocation
- ? { ...rawLocation, params: encodeParams(rawLocation.params) }
- : rawLocation,
- currentLocation
- )
+ let matchedRoute = matcher.resolve(matcherLocation, currentLocation)
const hash = encodeHash(rawLocation.hash || '')
// put back the unencoded params as given by the user (avoid the cost of decoding them)
- // TODO: normalize params if we accept numbers as raw values
matchedRoute.params =
'params' in rawLocation
- ? rawLocation.params!
+ ? normalizeParams(rawLocation.params)
: decodeParams(matchedRoute.params)
const fullPath = stringifyURL(stringifyQuery, {
export type TODO = any
export type RouteParamValue = string
-// TODO: should we allow more values like numbers and normalize them to strings?
-// type RouteParamValueRaw = RouteParamValue | number
+export type RouteParamValueRaw = RouteParamValue | number
export type RouteParams = Record<string, RouteParamValue | RouteParamValue[]>
-export type RouteParamsRaw = RouteParams
-// export type RouteParamsRaw = Record<
-// string,
-// RouteParamValueRaw | RouteParamValueRaw[]
-// >
+export type RouteParamsRaw = Record<
+ string,
+ RouteParamValueRaw | RouteParamValueRaw[]
+>
export interface RouteQueryAndHash {
query?: LocationQueryRaw
path: string
}
+export interface LocationAsNameRaw {
+ name: RouteRecordName
+ params?: RouteParamsRaw
+}
+
export interface LocationAsName {
name: RouteRecordName
+ params?: RouteParams
+}
+
+export interface LocationAsRelativeRaw {
params?: RouteParamsRaw
}
export interface LocationAsRelative {
- params?: RouteParamsRaw
+ params?: RouteParams
}
export interface RouteLocationOptions {
export type RouteLocationRaw =
| string
| (RouteQueryAndHash & LocationAsPath & RouteLocationOptions)
- | (RouteQueryAndHash & LocationAsName & RouteLocationOptions)
- | (RouteQueryAndHash & LocationAsRelative & RouteLocationOptions)
+ | (RouteQueryAndHash & LocationAsNameRaw & RouteLocationOptions)
+ | (RouteQueryAndHash & LocationAsRelativeRaw & RouteLocationOptions)
export interface RouteLocationMatched extends RouteRecordNormalized {
// components cannot be Lazy<RouteComponent>
-import { RouteParams, RouteComponent } from '../types'
+import { RouteParams, RouteComponent, RouteParamsRaw } from '../types'
import { hasSymbol } from '../injectionSymbols'
export * from './env'
}
export function applyToParams(
- fn: (v: string) => string,
- params: RouteParams | undefined
+ fn: (v: string | number) => string,
+ params: RouteParamsRaw | undefined
): RouteParams {
const newParams: RouteParams = {}