Dada una URL, por ejemplo, /path/path2/path3/123;sdf=df y una configuración de rutas:
{ path: 'path', data: { g: 'h' }, children: [ { path: 'path2', data: { c: 'd' }, children: [ { path: 'something', component: TestpageComponent, data: { a: 'b' } }, { path: 'path3/create', component: TestpageComponent, data: { b: 'c' } }, { path: 'path3/:id', component: TestpageComponent, data: { b: 'c' } }, ] } ] }, Lo que necesito es encontrar una configuración real para todos los segmentos para obtener un conjunto de resultados de todos los parámetros de data en todos los niveles (cada segmento de la URL).
Puedo dividir la URL en los segmentos por ejemplo
console.log(this.router.parseUrl(url));o para ser mas precisos
console.log(this.router.parseUrl(url).root.children['primary'].segments);que regresará
[{"path":"path","parameters":{}},{"path":"path2","parameters":{}},{"path":"and","parameters":{}},{"path":"123","parameters":{"sdf":"df"}}]Entonces, dividir la URL en segmentos no es un problema. Sin embargo, necesito obtener una configuración para cada segmento.
Puedo obtener la configuración real para todas las rutas con
console.log(this.router.config); Puedo ir con los segmentos a través del árbol de configuración y encontrar la rama que necesito, pero puede causar problemas, por ejemplo, al resolver :id contra create segmento. Por lo tanto, me gustaría usar la forma en que el enrutador resuelve la configuración de que si la implementación del enrutador interno cambia, no necesitaría cambiar la mía.
Ejemplo: imagine que tengo un 50% de las URL protegidas por algún tipo de protección (por ejemplo, solo los usuarios registrados pueden ir allí) y otro 50% no está protegido (se muestra para todos). Por lo tanto, en el nivel del menú de navegación (fuera de la router-outlet ) quiero mostrar solo los enlaces que son relevantes para el usuario actual, por lo que necesito saber qué rutas están protegidas por la guardia. Guardias/datos/lo que sea es solo un caso particular del problema.
No se ciña al ejemplo , estoy buscando una forma común de establecer la configuración para una URL en particular.
¿Es esto posible de alguna manera?
Con la versión 2.x, puede usar la función de recognize que el enrutador usa internamente para hacer coincidir una URL con un RouteStateSnapshot .
import { recognize } from '@angular/router/src/recognize'; recognize(null, this.router.config, this.router.parseUrl(url), url).subscribe(route => { var routeSnapshot = route.root.firstChild; // Go to all children to get actual route. // If you use routes with children you should have // the full tree here var childSnapshot = routeSnapshot.firstChild; while (childSnapshot != null) { childSnapshot = routeSnapshot.firstChild; if (childSnapshot != null) { routeSnapshot = childSnapshot; } } let routeData = routeSnapshot.data || {}; // routeData['a']... }); Lamentablemente, parece que ya no funciona con la versión 4.x. Para la versión 4.x, he creado una solicitud de extracción para agregar un nuevo método al Router para exponer la función de reconocimiento.
https://github.com/angular/angular/issues/15826
Otra nota al margen. tiene sentido manejar también los errores de la promesa (ya sea del método de reconocimiento o del nuevo enrutador), agregando .catch((rej) => { // some code if it fails to resolve route }) . Puede suceder que no se resuelva la url->routestatesnapshot. Ya sea porque la URL es incorrecta o usa rutas asíncronas a través LoadChildren y las rutas aún no están cargadas. Las migas de pan funcionan muy bien incluso con rutas asíncronas. Si lo usa para verificar permisos, por ejemplo a través de una directiva, debe tener cuidado si usa rutas asíncronas.
Hay otra forma de obtener la configuración de datos para las rutas. Implica saber cuál es la propiedad key en el objeto de datos.
En su componente puede obtener los datos para esa ruta exacta con
this.route.snapshot.data['key']Puede obtener los datos de los padres con
this.route.snapshot.parent.data['key']O incluso los datos de los abuelos con
this.route.snapshot.parent.parent.data['key']Dado que está utilizando diferentes claves en todas sus rutas, eso lo hace más difícil. En ese caso, necesitaría obtener una lista de las claves e iterar sobre eso:
let keys = Object.keys(this.route.snapshot.data); keys.map(x => { console.log('key', x); console.log('data', this.route.snapshot.data[x]); }Además, si conoce los segmentos de su URL, incluso puede hacer coincidir eso para obtener la configuración de una ruta en particular:
let configForRoute = this.router.config.find(x => x.path === this. route.snapshot.url.toString()) let dataForSegment = this.router.config.find(x => x.path === 'somePath').data['key']Una solución cruda para obtener todos los datos que necesita se vería así:
obj = {}; getData(routeData){ let keys = Object.keys(routeData); keys.map(x => this.obj[x] = routeData[x]) } this.getData(this.route.snapshot.parent.parent.data); this.getData(this.route.snapshot.parent.data); this.getData(this.route.snapshot.data); console.log(obj);Con suerte, esto lo ayudará a encaminarse para obtener los datos que necesita.
EDITAR
Puede que haya entendido mal la pregunta original.
Desde la adición de:
¿Por qué necesitaría eso? Imagine que tengo un 50% de las URL protegidas por algún tipo de protección (por ejemplo, solo los usuarios registrados pueden ir allí) y otro 50% no está protegido (se muestra para todos). Por lo tanto, en el nivel del menú de navegación (fuera de la salida del enrutador) quiero mostrar solo los enlaces que son relevantes para el usuario actual, por lo que necesito saber qué rutas están protegidas por la guardia. Guardias/datos/lo que sea es solo un caso particular del problema.
La forma en que resolví este problema de ocultar enlaces que los usuarios no autenticados podían ver u ocultar enlaces que los usuarios no autorizados podían ver fue crear una función en mi servicio de autenticación que puede verificar si un usuario está autenticado o autorizado. Es la misma función que también utilizan mis guardias en mis rutas.
Por ejemplo, puedo tener un guardia CheckPermissions en mis rutas con los datos de la ruta data: { permissions:[permission1, permission2] } Detrás de escena, este guardia usa una función en el servicio de autenticación para verificar si el usuario tiene permiso para usar los permisos enumerados. en el campo de datos. También puedo usar esa misma función del servicio de autenticación para ocultar enlaces en mi menú principal con *ngIf="authSvc.CheckPermission(permission1) etc. De esta manera no tengo que duplicar la lógica en ninguna parte. En última instancia, los puntos finales de la API deberían ser lado del servidor protegido también.
En cuanto a poder darle al enrutador una URL y recuperar la ruta que coincide sin navegar, no puedo encontrar una forma documentada de hacerlo. Espero que esto sea al menos un poco de ayuda.