From 46b5862d22289a8ad9ef4b30fee8429dca922289 Mon Sep 17 00:00:00 2001 From: Ricardo Chavarria Date: Thu, 23 Oct 2025 14:43:27 -0600 Subject: [PATCH] translate: translations for routing guides Fixes #51 --- .../src/app/routing/sub-navigation-data.ts | 34 +- .../guide/routing/common-router-tasks.en.md | 187 +++++++ .../guide/routing/common-router-tasks.md | 138 ++--- .../routing/customizing-route-behavior.en.md | 473 ++++++++++++++++++ .../routing/customizing-route-behavior.md | 230 ++++----- .../guide/routing/data-resolvers.en.md | 298 +++++++++++ .../content/guide/routing/data-resolvers.md | 106 ++-- .../content/guide/routing/define-routes.en.md | 413 +++++++++++++++ .../content/guide/routing/define-routes.md | 210 ++++---- .../guide/routing/lifecycle-and-events.en.md | 243 +++++++++ .../guide/routing/lifecycle-and-events.md | 148 +++--- .../guide/routing/navigate-to-routes.en.md | 171 +++++++ .../guide/routing/navigate-to-routes.md | 86 ++-- .../src/content/guide/routing/overview.en.md | 32 ++ adev-es/src/content/guide/routing/overview.md | 38 +- .../guide/routing/read-route-state.en.md | 288 +++++++++++ .../content/guide/routing/read-route-state.md | 124 ++--- .../guide/routing/redirecting-routes.en.md | 144 ++++++ .../guide/routing/redirecting-routes.md | 94 ++-- .../guide/routing/rendering-strategies.en.md | 139 +++++ .../guide/routing/rendering-strategies.md | 162 +++--- .../content/guide/routing/route-guards.en.md | 208 ++++++++ .../src/content/guide/routing/route-guards.md | 118 ++--- .../routing/route-transition-animations.en.md | 203 ++++++++ .../routing/route-transition-animations.md | 136 ++--- .../guide/routing/router-reference.en.md | 119 +++++ .../content/guide/routing/router-reference.md | 142 +++--- .../guide/routing/router-tutorial.en.md | 275 ++++++++++ .../content/guide/routing/router-tutorial.md | 248 ++++----- .../routing/routing-with-urlmatcher.en.md | 116 +++++ .../guide/routing/routing-with-urlmatcher.md | 100 ++-- .../routing/show-routes-with-outlets.en.md | 170 +++++++ .../guide/routing/show-routes-with-outlets.md | 70 +-- .../src/content/guide/routing/testing.en.md | 341 +++++++++++++ adev-es/src/content/guide/routing/testing.md | 74 +-- 35 files changed, 4949 insertions(+), 1129 deletions(-) create mode 100644 adev-es/src/content/guide/routing/common-router-tasks.en.md create mode 100644 adev-es/src/content/guide/routing/customizing-route-behavior.en.md create mode 100644 adev-es/src/content/guide/routing/data-resolvers.en.md create mode 100644 adev-es/src/content/guide/routing/define-routes.en.md create mode 100644 adev-es/src/content/guide/routing/lifecycle-and-events.en.md create mode 100644 adev-es/src/content/guide/routing/navigate-to-routes.en.md create mode 100644 adev-es/src/content/guide/routing/overview.en.md create mode 100644 adev-es/src/content/guide/routing/read-route-state.en.md create mode 100644 adev-es/src/content/guide/routing/redirecting-routes.en.md create mode 100644 adev-es/src/content/guide/routing/rendering-strategies.en.md create mode 100644 adev-es/src/content/guide/routing/route-guards.en.md create mode 100644 adev-es/src/content/guide/routing/route-transition-animations.en.md create mode 100644 adev-es/src/content/guide/routing/router-reference.en.md create mode 100644 adev-es/src/content/guide/routing/router-tutorial.en.md create mode 100644 adev-es/src/content/guide/routing/routing-with-urlmatcher.en.md create mode 100644 adev-es/src/content/guide/routing/show-routes-with-outlets.en.md create mode 100644 adev-es/src/content/guide/routing/testing.en.md diff --git a/adev-es/src/app/routing/sub-navigation-data.ts b/adev-es/src/app/routing/sub-navigation-data.ts index fb15704..179d4ed 100644 --- a/adev-es/src/app/routing/sub-navigation-data.ts +++ b/adev-es/src/app/routing/sub-navigation-data.ts @@ -326,89 +326,89 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ ], }, { - label: 'Routing', + label: 'Enrutamiento', status: 'updated', children: [ { - label: 'Overview', + label: 'Visión general', path: 'guide/routing', contentPath: 'guide/routing/overview', }, { - label: 'Define routes', + label: 'Definir rutas', path: 'guide/routing/define-routes', contentPath: 'guide/routing/define-routes', }, { - label: 'Show routes with Outlets', + label: 'Mostrar rutas con outlets', path: 'guide/routing/show-routes-with-outlets', contentPath: 'guide/routing/show-routes-with-outlets', }, { - label: 'Navigate to routes', + label: 'Navegar a rutas', path: 'guide/routing/navigate-to-routes', contentPath: 'guide/routing/navigate-to-routes', }, { - label: 'Read route state', + label: 'Leer estado de ruta', path: 'guide/routing/read-route-state', contentPath: 'guide/routing/read-route-state', }, { - label: 'Redirecting routes', + label: 'Redirigir rutas', path: 'guide/routing/redirecting-routes', contentPath: 'guide/routing/redirecting-routes', }, { - label: 'Control route access with guards', + label: 'Controlar acceso a rutas con guards', path: 'guide/routing/route-guards', contentPath: 'guide/routing/route-guards', }, { - label: 'Route data resolvers', + label: 'Resolvers de datos de ruta', path: 'guide/routing/data-resolvers', contentPath: 'guide/routing/data-resolvers', }, { - label: 'Lifecycle and events', + label: 'Ciclo de vida y eventos', path: 'guide/routing/lifecycle-and-events', contentPath: 'guide/routing/lifecycle-and-events', }, { - label: 'Testing routing and navigation', + label: 'Pruebas de routing y navegación', path: 'guide/routing/testing', contentPath: 'guide/routing/testing', status: 'new', }, { - label: 'Other routing tasks', + label: 'Otras tareas de routing', path: 'guide/routing/common-router-tasks', contentPath: 'guide/routing/common-router-tasks', }, { - label: 'Creating custom route matches', + label: 'Creando coincidencias de ruta personalizadas', path: 'guide/routing/routing-with-urlmatcher', contentPath: 'guide/routing/routing-with-urlmatcher', }, { - label: 'Rendering strategies', + label: 'Estrategias de renderizado', path: 'guide/routing/rendering-strategies', contentPath: 'guide/routing/rendering-strategies', status: 'new', }, { - label: 'Customizing route behavior', + label: 'Personalizar comportamiento de ruta', path: 'guide/routing/customizing-route-behavior', contentPath: 'guide/routing/customizing-route-behavior', status: 'new', }, { - label: 'Router reference', + label: 'Referencia del Router', path: 'guide/routing/router-reference', contentPath: 'guide/routing/router-reference', }, { - label: 'Route transition animations', + label: 'Animaciones de transición de ruta', path: 'guide/routing/route-transition-animations', contentPath: 'guide/routing/route-transition-animations', }, diff --git a/adev-es/src/content/guide/routing/common-router-tasks.en.md b/adev-es/src/content/guide/routing/common-router-tasks.en.md new file mode 100644 index 0000000..1ae7d94 --- /dev/null +++ b/adev-es/src/content/guide/routing/common-router-tasks.en.md @@ -0,0 +1,187 @@ +# Other common Routing Tasks + +This guide covers some other common tasks associated with using Angular router in your application. + +## Getting route information + +Often, as a user navigates your application, you want to pass information from one component to another. +For example, consider an application that displays a shopping list of grocery items. +Each item in the list has a unique `id`. +To edit an item, users click an Edit button, which opens an `EditGroceryItem` component. +You want that component to retrieve the `id` for the grocery item so it can display the right information to the user. + +Use a route to pass this type of information to your application components. +To do so, you use the [`withComponentInputBinding`](api/router/withComponentInputBinding) feature with `provideRouter` or the `bindToComponentInputs` option of `RouterModule.forRoot`. + +To get information from a route: + + + + + +Add the `withComponentInputBinding` feature to the `provideRouter` method. + +```ts +providers: [ + provideRouter(appRoutes, withComponentInputBinding()), +] +``` + + + + + +Update the component to have an `input()` property matching the name of the parameter. + +```ts +id = input.required() +hero = computed(() => this.service.getHero(id)); +``` + + + +The router assigns values to all inputs based on the current route when `withComponentInputBinding` is enabled. +The router assigns `undefined` if no route data matches the input key, such as when an optional query parameter is missing. +You should include `undefined` in the `input`'s type when there's a possibility that an input might not be matched by the route. + +Provide a default value by either using the `transform` option on the input or managing a local state with a `linkedSignal`. + +```ts +id = input.required({ + transform: (maybeUndefined: string | undefined) => maybeUndefined ?? '0', +}); +// or +id = input(); +internalId = linkedSignal(() => this.id() ?? getDefaultId()); +``` + + + + +NOTE: You can bind all route data with key, value pairs to component inputs: static or resolved route data, path parameters, matrix parameters, and query parameters. +If you want to use the parent components route info you will need to set the router `paramsInheritanceStrategy` option: +`withRouterConfig({paramsInheritanceStrategy: 'always'})` + +## Displaying a 404 page + +To display a 404 page, set up a [wildcard route](guide/routing/common-router-tasks#setting-up-wildcard-routes) with the `component` property set to the component you'd like to use for your 404 page as follows: + +```ts +const routes: Routes = [ + { path: 'first-component', component: FirstComponent }, + { path: 'second-component', component: SecondComponent }, + { path: '**', component: PageNotFoundComponent }, // Wildcard route for a 404 page +]; +``` + +The last route with the `path` of `**` is a wildcard route. +The router selects this route if the requested URL doesn't match any of the paths earlier in the list and sends the user to the `PageNotFoundComponent`. + +## Link parameters array + +A link parameters array holds the following ingredients for router navigation: + +- The path of the route to the destination component +- Required and optional route parameters that go into the route URL + +Bind the `RouterLink` directive to such an array like this: + +```angular-html +Heroes +``` + +The following is a two-element array when specifying a route parameter: + +```angular-html + + {{ hero.id }}{{ hero.name }} + +``` + +Provide optional route parameters in an object, as in `{ foo: 'foo' }`: + +```angular-html +Crisis Center +``` + +These three examples cover the needs of an application with one level of routing. +However, with a child router, such as in the crisis center, you create new link array possibilities. + +The following minimal `RouterLink` example builds upon a specified default child route for the crisis center. + +```angular-html +Crisis Center +``` + +Review the following: + +- The first item in the array identifies the parent route \(`/crisis-center`\) +- There are no parameters for this parent route +- There is no default for the child route so you need to pick one +- You're navigating to the `CrisisListComponent`, whose route path is `/`, but you don't need to explicitly add the slash + +Consider the following router link that navigates from the root of the application down to the Dragon Crisis: + +```angular-html +Dragon Crisis +``` + +- The first item in the array identifies the parent route \(`/crisis-center`\) +- There are no parameters for this parent route +- The second item identifies the child route details about a particular crisis \(`/:id`\) +- The details child route requires an `id` route parameter +- You added the `id` of the Dragon Crisis as the second item in the array \(`1`\) +- The resulting path is `/crisis-center/1` + +You could also redefine the `AppComponent` template with Crisis Center routes exclusively: + +```angular-ts +@Component({ + template: ` +

Angular Router

+ + + ` +}) +export class AppComponent {} +``` + +In summary, you can write applications with one, two or more levels of routing. +The link parameters array affords the flexibility to represent any routing depth and any legal sequence of route paths, \(required\) router parameters, and \(optional\) route parameter objects. + +## `LocationStrategy` and browser URL styles + +When the router navigates to a new component view, it updates the browser's location and history with a URL for that view. + +Modern HTML5 browsers support [history.pushState](https://developer.mozilla.org/docs/Web/API/History_API/Working_with_the_History_API#adding_and_modifying_history_entries 'HTML5 browser history push-state'), a technique that changes a browser's location and history without triggering a server page request. +The router can compose a "natural" URL that is indistinguishable from one that would otherwise require a page load. + +Here's the Crisis Center URL in this "HTML5 pushState" style: + +```text +localhost:3002/crisis-center +``` + +Older browsers send page requests to the server when the location URL changes unless the change occurs after a "#" \(called the "hash"\). +Routers can take advantage of this exception by composing in-application route URLs with hashes. +Here's a "hash URL" that routes to the Crisis Center. + +```text +localhost:3002/src/#/crisis-center +``` + +The router supports both styles with two `LocationStrategy` providers: + +| Providers | Details | +| :--------------------- | :----------------------------------- | +| `PathLocationStrategy` | The default "HTML5 pushState" style. | +| `HashLocationStrategy` | The "hash URL" style. | + +The `RouterModule.forRoot()` function sets the `LocationStrategy` to the `PathLocationStrategy`, which makes it the default strategy. +You also have the option of switching to the `HashLocationStrategy` with an override during the bootstrapping process. + +HELPFUL: For more information on providers and the bootstrap process, see [Dependency Injection](guide/di/dependency-injection-providers). diff --git a/adev-es/src/content/guide/routing/common-router-tasks.md b/adev-es/src/content/guide/routing/common-router-tasks.md index 1ae7d94..56cf155 100644 --- a/adev-es/src/content/guide/routing/common-router-tasks.md +++ b/adev-es/src/content/guide/routing/common-router-tasks.md @@ -1,25 +1,25 @@ -# Other common Routing Tasks +# Otras tareas comunes de enrutamiento -This guide covers some other common tasks associated with using Angular router in your application. +Esta guía cubre algunas otras tareas comunes asociadas con el uso de Angular router en tu aplicación. -## Getting route information +## Obtener información de la ruta -Often, as a user navigates your application, you want to pass information from one component to another. -For example, consider an application that displays a shopping list of grocery items. -Each item in the list has a unique `id`. -To edit an item, users click an Edit button, which opens an `EditGroceryItem` component. -You want that component to retrieve the `id` for the grocery item so it can display the right information to the user. +A menudo, cuando un usuario navega por tu aplicación, quieres pasar información de un componente a otro. +Por ejemplo, considera una aplicación que muestra una lista de compras de artículos de comestibles. +Cada elemento en la lista tiene un `id` único. +Para editar un elemento, los usuarios hacen clic en un botón Editar, que abre un componente `EditGroceryItem`. +Quieres que ese componente recupere el `id` del artículo de comestible para que pueda mostrar la información correcta al usuario. -Use a route to pass this type of information to your application components. -To do so, you use the [`withComponentInputBinding`](api/router/withComponentInputBinding) feature with `provideRouter` or the `bindToComponentInputs` option of `RouterModule.forRoot`. +Usa una ruta para pasar este tipo de información a los componentes de tu aplicación. +Para hacerlo, usas la funcionalidad [`withComponentInputBinding`](api/router/withComponentInputBinding) con `provideRouter` o la opción `bindToComponentInputs` de `RouterModule.forRoot`. -To get information from a route: +Para obtener información de una ruta: - + -Add the `withComponentInputBinding` feature to the `provideRouter` method. +Agrega la funcionalidad `withComponentInputBinding` al método `provideRouter`. ```ts providers: [ @@ -29,9 +29,9 @@ providers: [ - + -Update the component to have an `input()` property matching the name of the parameter. +Actualiza el componente para que tenga una propiedad `input()` que coincida con el nombre del parámetro. ```ts id = input.required() @@ -39,18 +39,18 @@ hero = computed(() => this.service.getHero(id)); ``` - -The router assigns values to all inputs based on the current route when `withComponentInputBinding` is enabled. -The router assigns `undefined` if no route data matches the input key, such as when an optional query parameter is missing. -You should include `undefined` in the `input`'s type when there's a possibility that an input might not be matched by the route. + +El router asigna valores a todas las entradas según la ruta actual cuando `withComponentInputBinding` está habilitado. +El router asigna `undefined` si no hay datos de ruta que coincidan con la clave de entrada, como cuando falta un parámetro de consulta opcional. +Debes incluir `undefined` en el tipo del `input` cuando existe la posibilidad de que una entrada no coincida con la ruta. -Provide a default value by either using the `transform` option on the input or managing a local state with a `linkedSignal`. +Proporciona un valor predeterminado usando la opción `transform` en el input o gestionando un estado local con un `linkedSignal`. ```ts id = input.required({ transform: (maybeUndefined: string | undefined) => maybeUndefined ?? '0', }); -// or +// o id = input(); internalId = linkedSignal(() => this.id() ?? getDefaultId()); ``` @@ -58,39 +58,39 @@ internalId = linkedSignal(() => this.id() ?? getDefaultId()); -NOTE: You can bind all route data with key, value pairs to component inputs: static or resolved route data, path parameters, matrix parameters, and query parameters. -If you want to use the parent components route info you will need to set the router `paramsInheritanceStrategy` option: +NOTA: Puedes vincular todos los datos de ruta con pares clave-valor a las entradas del componente: datos de ruta estáticos o resueltos, parámetros de ruta, parámetros de matriz y parámetros de consulta. +Si deseas usar la información de ruta del componente padre, necesitarás configurar la opción `paramsInheritanceStrategy` del router: `withRouterConfig({paramsInheritanceStrategy: 'always'})` -## Displaying a 404 page +## Mostrar una página 404 -To display a 404 page, set up a [wildcard route](guide/routing/common-router-tasks#setting-up-wildcard-routes) with the `component` property set to the component you'd like to use for your 404 page as follows: +Para mostrar una página 404, configura una [ruta comodín](guide/routing/common-router-tasks#setting-up-wildcard-routes) con la propiedad `component` establecida en el componente que deseas usar para tu página 404 de la siguiente manera: ```ts const routes: Routes = [ { path: 'first-component', component: FirstComponent }, { path: 'second-component', component: SecondComponent }, - { path: '**', component: PageNotFoundComponent }, // Wildcard route for a 404 page + { path: '**', component: PageNotFoundComponent }, // Ruta comodín para una página 404 ]; ``` -The last route with the `path` of `**` is a wildcard route. -The router selects this route if the requested URL doesn't match any of the paths earlier in the list and sends the user to the `PageNotFoundComponent`. +La última ruta con el `path` de `**` es una ruta comodín. +El router selecciona esta ruta si la URL solicitada no coincide con ninguna de las rutas anteriores en la lista y envía al usuario al `PageNotFoundComponent`. -## Link parameters array +## Array de parámetros de enlace -A link parameters array holds the following ingredients for router navigation: +Un array de parámetros de enlace contiene los siguientes ingredientes para la navegación del router: -- The path of the route to the destination component -- Required and optional route parameters that go into the route URL +- La ruta del camino al componente de destino +- Parámetros de ruta requeridos y opcionales que van en la URL de la ruta -Bind the `RouterLink` directive to such an array like this: +Vincula la directiva `RouterLink` a tal array de esta manera: ```angular-html Heroes ``` -The following is a two-element array when specifying a route parameter: +Lo siguiente es un array de dos elementos al especificar un parámetro de ruta: ```angular-html @@ -98,42 +98,42 @@ The following is a two-element array when specifying a route parameter: ``` -Provide optional route parameters in an object, as in `{ foo: 'foo' }`: +Proporciona parámetros de ruta opcionales en un objeto, como en `{ foo: 'foo' }`: ```angular-html Crisis Center ``` -These three examples cover the needs of an application with one level of routing. -However, with a child router, such as in the crisis center, you create new link array possibilities. +Estos tres ejemplos cubren las necesidades de una aplicación con un nivel de enrutamiento. +Sin embargo, con un router hijo, como en el centro de crisis, creas nuevas posibilidades de array de enlaces. -The following minimal `RouterLink` example builds upon a specified default child route for the crisis center. +El siguiente ejemplo mínimo de `RouterLink` se basa en una ruta hija predeterminada especificada para el centro de crisis. ```angular-html Crisis Center ``` -Review the following: +Revisa lo siguiente: -- The first item in the array identifies the parent route \(`/crisis-center`\) -- There are no parameters for this parent route -- There is no default for the child route so you need to pick one -- You're navigating to the `CrisisListComponent`, whose route path is `/`, but you don't need to explicitly add the slash +- El primer elemento en el array identifica la ruta padre \(`/crisis-center`\) +- No hay parámetros para esta ruta padre +- No hay un valor predeterminado para la ruta hija, por lo que necesitas elegir uno +- Estás navegando al `CrisisListComponent`, cuya ruta es `/`, pero no necesitas agregar explícitamente la barra diagonal -Consider the following router link that navigates from the root of the application down to the Dragon Crisis: +Considera el siguiente enlace de router que navega desde la raíz de la aplicación hasta el Dragon Crisis: ```angular-html Dragon Crisis ``` -- The first item in the array identifies the parent route \(`/crisis-center`\) -- There are no parameters for this parent route -- The second item identifies the child route details about a particular crisis \(`/:id`\) -- The details child route requires an `id` route parameter -- You added the `id` of the Dragon Crisis as the second item in the array \(`1`\) -- The resulting path is `/crisis-center/1` +- El primer elemento en el array identifica la ruta padre \(`/crisis-center`\) +- No hay parámetros para esta ruta padre +- El segundo elemento identifica los detalles de la ruta hija sobre una crisis en particular \(`/:id`\) +- La ruta hija de detalles requiere un parámetro de ruta `id` +- Agregaste el `id` del Dragon Crisis como el segundo elemento en el array \(`1`\) +- La ruta resultante es `/crisis-center/1` -You could also redefine the `AppComponent` template with Crisis Center routes exclusively: +También podrías redefinir la plantilla de `AppComponent` con rutas del Crisis Center exclusivamente: ```angular-ts @Component({ @@ -150,38 +150,38 @@ You could also redefine the `AppComponent` template with Crisis Center routes ex export class AppComponent {} ``` -In summary, you can write applications with one, two or more levels of routing. -The link parameters array affords the flexibility to represent any routing depth and any legal sequence of route paths, \(required\) router parameters, and \(optional\) route parameter objects. +En resumen, puedes escribir aplicaciones con uno, dos o más niveles de enrutamiento. +El array de parámetros de enlace ofrece la flexibilidad para representar cualquier profundidad de enrutamiento y cualquier secuencia legal de rutas, parámetros de router \(requeridos\) y objetos de parámetros de ruta \(opcionales\). -## `LocationStrategy` and browser URL styles +## `LocationStrategy` y estilos de URL del navegador -When the router navigates to a new component view, it updates the browser's location and history with a URL for that view. +Cuando el router navega a una nueva vista de componente, actualiza la ubicación y el historial del navegador con una URL para esa vista. -Modern HTML5 browsers support [history.pushState](https://developer.mozilla.org/docs/Web/API/History_API/Working_with_the_History_API#adding_and_modifying_history_entries 'HTML5 browser history push-state'), a technique that changes a browser's location and history without triggering a server page request. -The router can compose a "natural" URL that is indistinguishable from one that would otherwise require a page load. +Los navegadores modernos HTML5 soportan [history.pushState](https://developer.mozilla.org/docs/Web/API/History_API/Working_with_the_History_API#adding_and_modifying_history_entries 'HTML5 browser history push-state'), una técnica que cambia la ubicación y el historial de un navegador sin disparar una petición de página al servidor. +El router puede componer una URL "natural" que es indistinguible de una que de otro modo requeriría una carga de página. -Here's the Crisis Center URL in this "HTML5 pushState" style: +Aquí está la URL del Crisis Center en este estilo "HTML5 pushState": ```text localhost:3002/crisis-center ``` -Older browsers send page requests to the server when the location URL changes unless the change occurs after a "#" \(called the "hash"\). -Routers can take advantage of this exception by composing in-application route URLs with hashes. -Here's a "hash URL" that routes to the Crisis Center. +Los navegadores más antiguos envían peticiones de página al servidor cuando la URL de ubicación cambia, a menos que el cambio ocurra después de un "#" \(llamado "hash"\). +Los routers pueden aprovechar esta excepción componiendo URLs de ruta dentro de la aplicación con hashes. +Aquí hay una "URL hash" que enruta al Crisis Center. ```text localhost:3002/src/#/crisis-center ``` -The router supports both styles with two `LocationStrategy` providers: +El router soporta ambos estilos con dos proveedores `LocationStrategy`: -| Providers | Details | -| :--------------------- | :----------------------------------- | -| `PathLocationStrategy` | The default "HTML5 pushState" style. | -| `HashLocationStrategy` | The "hash URL" style. | +| Providers | Details | +| :--------------------- | :-------------------------------------------- | +| `PathLocationStrategy` | El estilo predeterminado "HTML5 pushState". | +| `HashLocationStrategy` | El estilo "hash URL". | -The `RouterModule.forRoot()` function sets the `LocationStrategy` to the `PathLocationStrategy`, which makes it the default strategy. -You also have the option of switching to the `HashLocationStrategy` with an override during the bootstrapping process. +La función `RouterModule.forRoot()` establece el `LocationStrategy` al `PathLocationStrategy`, lo que lo convierte en la estrategia predeterminada. +También tienes la opción de cambiar al `HashLocationStrategy` con una sobrescritura durante el proceso de bootstrapping. -HELPFUL: For more information on providers and the bootstrap process, see [Dependency Injection](guide/di/dependency-injection-providers). +ÚTIL: Para más información sobre proveedores y el proceso de bootstrap, consulta [Inyección de Dependencias](guide/di/dependency-injection-providers). diff --git a/adev-es/src/content/guide/routing/customizing-route-behavior.en.md b/adev-es/src/content/guide/routing/customizing-route-behavior.en.md new file mode 100644 index 0000000..6ae475f --- /dev/null +++ b/adev-es/src/content/guide/routing/customizing-route-behavior.en.md @@ -0,0 +1,473 @@ +# Customizing route behavior + +Angular Router provides powerful extension points that allow you to customize how routes behave in your application. While the default routing behavior works well for most applications, specific requirements often demand custom implementations for performance optimization, specialized URL handling, or complex routing logic. + +Route customization can become valuable when your application needs: + +- **Component state preservation** across navigations to avoid re-fetching data +- **Strategic lazy module loading** based on user behavior or network conditions +- **External URL integration** or handling Angular routes alongside legacy systems +- **Dynamic route matching** based on runtime conditions beyond simple path + patterns + +NOTE: Before implementing custom strategies, ensure the default router behavior doesn't meet your needs. Angular's default routing is optimized for common use cases and provides the best balance of performance and simplicity. Customizing route strategies can create additional code complexity and have performance implications on memory usage if not carefully managed. + +Angular Router exposes four main areas for customization: + + + + + + + + +## Route reuse strategy + +Route reuse strategy controls whether Angular destroys and recreates components during navigation or preserves them for reuse. By default, Angular destroys component instances when navigating away from a route and creates new instances when navigating back. + +### When to implement route reuse + +Custom route reuse strategies benefit applications that need: + +- **Form state preservation** - Keep partially completed forms when users navigate away and return +- **Expensive data retention** - Avoid re-fetching large datasets or complex calculations +- **Scroll position maintenance** - Preserve scroll positions in long lists or infinite scroll implementations +- **Tab-like interfaces** - Maintain component state when switching between tabs + +### Creating a custom route reuse strategy + +Angular's `RouteReuseStrategy` class allows you to customize navigation behavior through the concept of "detached route handles." + +"Detached route handles" are Angular's way of storing component instances and their entire view hierarchy. When a route is detached, Angular preserves the component instance, its child components, and all associated state in memory. This preserved state can later be reattached when navigating back to the route. + +The `RouteReuseStrategy` class provides five methods that control the lifecycle of route components: + +| Method | Description | +| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | +| [`shouldDetach`](api/router/RouteReuseStrategy#shouldDetach) | Determines if a route should be stored for later reuse when navigating away | +| [`store`](api/router/RouteReuseStrategy#store) | Stores the detached route handle when `shouldDetach` returns true | +| [`shouldAttach`](api/router/RouteReuseStrategy#shouldAttach) | Determines if a stored route should be reattached when navigating to it | +| [`retrieve`](api/router/RouteReuseStrategy#retrieve) | Returns the previously stored route handle for reattachment | +| [`shouldReuseRoute`](api/router/RouteReuseStrategy#shouldReuseRoute) | Determines if the router should reuse the current route instance instead of destroying it during navigation | + +The following example demonstrates a custom route reuse strategy that selectively preserves component state based on route metadata: + +```ts +import { RouteReuseStrategy, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router'; +import { Injectable } from '@angular/core'; + +@Injectable() +export class CustomRouteReuseStrategy implements RouteReuseStrategy { + private handlers = new Map(); + + shouldDetach(route: ActivatedRouteSnapshot): boolean { + // Determines if a route should be stored for later reuse + return route.data['reuse'] === true; + } + + store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle | null): void { + // Stores the detached route handle when shouldDetach returns true + if (handle && route.data['reuse'] === true) { + const key = this.getRouteKey(route); + this.handlers.set(key, handle); + } + } + + shouldAttach(route: ActivatedRouteSnapshot): boolean { + // Checks if a stored route should be reattached + const key = this.getRouteKey(route); + return route.data['reuse'] === true && this.handlers.has(key); + } + + retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null { + // Returns the stored route handle for reattachment + const key = this.getRouteKey(route); + return route.data['reuse'] === true ? this.handlers.get(key) ?? null : null; + } + + shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { + // Determines if the router should reuse the current route instance + return future.routeConfig === curr.routeConfig; + } + + private getRouteKey(route: ActivatedRouteSnapshot): string { + return route.routeConfig ?? ''; + } +} +``` + +### Configuring a route to use a custom route reuse strategy + +Routes can opt into reuse behavior through route configuration metadata. This approach keeps the reuse logic separate from component code, making it easy to adjust behavior without modifying components: + +```ts +export const routes: Routes = [ + { + path: 'products', + component: ProductListComponent, + data: { reuse: true } // Component state persists across navigations + }, + { + path: 'products/:id', + component: ProductDetailComponent, + // No reuse flag - component recreates on each navigation + }, + { + path: 'search', + component: SearchComponent, + data: { reuse: true } // Preserves search results and filter state + } +]; +``` + +You can also configure a custom route reuse strategy at the application level through Angular's dependency injection system. In this case, Angular creates a single instance of the strategy that manages all route reuse decisions throughout the application: + +```ts +export const appConfig: ApplicationConfig = { + providers: [ + provideRouter(routes), + { provide: RouteReuseStrategy, useClass: CustomRouteReuseStrategy } + ] +}; +``` + +## Preloading strategy + +Preloading strategies determine when Angular loads lazy-loaded route modules in the background. While lazy loading improves initial load time by deferring module downloads, users still experience a delay when first navigating to a lazy route. Preloading strategies eliminate this delay by loading modules before users request them. + +### Built-in preloading strategies + +Angular provides two preloading strategies out of the box: + +| Strategy | Description | +| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | +| [`NoPreloading`](api/router/NoPreloading) | The default strategy that disables all preloading. In other words, modules only load when users navigate to them | +| [`PreloadAllModules`](api/router/PreloadAllModules) | Loads all lazy-loaded modules immediately after the initial navigation | + +The `PreloadAllModules` strategy can be configured as follows: + +```ts +import { ApplicationConfig } from '@angular/core'; +import { provideRouter, withPreloading, PreloadAllModules } from '@angular/router'; +import { routes } from './app.routes'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideRouter( + routes, + withPreloading(PreloadAllModules) + ) + ] +}; +``` + +The `PreloadAllModules` strategy works well for small to medium applications where downloading all modules doesn't significantly impact performance. However, larger applications with many feature modules might benefit from more selective preloading. + +### Creating a custom preloading strategy + +Custom preloading strategies implement the `PreloadingStrategy` interface, which requires a single `preload` method. This method receives the route configuration and a function that triggers the actual module load. The strategy returns an Observable that emits when preloading completes or an empty Observable to skip preloading: + +```ts +import { Injectable } from '@angular/core'; +import { PreloadingStrategy, Route } from '@angular/router'; +import { Observable, of, timer } from 'rxjs'; +import { mergeMap } from 'rxjs/operators'; + +@Injectable() +export class SelectivePreloadingStrategy implements PreloadingStrategy { + preload(route: Route, load: () => Observable): Observable { + // Only preload routes marked with data: { preload: true } + if (route.data?.['preload']) { + return load(); + } + return of(null); + } +} +``` + +This selective strategy checks route metadata to determine preloading behavior. Routes can opt into preloading through their configuration: + +```ts +import { Routes } from '@angular/router'; + +export const routes: Routes = [ + { + path: 'dashboard', + loadChildren: () => import('./dashboard/dashboard.routes'), + data: { preload: true } // Preload immediately after initial navigation + }, + { + path: 'reports', + loadChildren: () => import('./reports/reports.routes'), + data: { preload: false } // Only load when user navigates to reports + }, + { + path: 'admin', + loadChildren: () => import('./admin/admin.routes') + // No preload flag - won't be preloaded + } +]; +``` + +### Performance considerations for preloading + +Preloading impacts both network usage and memory consumption. Each preloaded module consumes bandwidth and increases the application's memory footprint. Mobile users on metered connections might prefer minimal preloading, while desktop users on fast networks can handle aggressive preloading strategies. + +The timing of preloading also matters. Immediate preloading after initial load might compete with other critical resources like images or API calls. Strategies should consider the application's post-load behavior and coordinate with other background tasks to avoid performance degradation. + +Browser resource limits also affect preloading behavior. Browsers limit concurrent HTTP connections, so aggressive preloading might queue behind other requests. Service workers can help by providing fine-grained control over caching and network requests, complementing the preloading strategy. + +## URL handling strategy + +URL handling strategies determine which URLs the Angular router processes versus which ones it ignores. By default, Angular attempts to handle all navigation events within the application, but real-world applications often need to coexist with other systems, handle external links, or integrate with legacy applications that manage their own routes. + +The `UrlHandlingStrategy` class gives you control over this boundary between Angular-managed routes and external URLs. This becomes essential when migrating applications to Angular incrementally or when Angular applications need to share URL space with other frameworks. + +### Implementing a custom URL handling strategy + +Custom URL handling strategies extend the `UrlHandlingStrategy` class and implement three methods. The `shouldProcessUrl` method determines whether Angular should handle a given URL, `extract` returns the portion of the URL that Angular should process, and `merge` combines the URL fragment with the rest of the URL: + +```ts +import { Injectable } from '@angular/core'; +import { UrlHandlingStrategy, UrlTree } from '@angular/router'; + +@Injectable() +export class CustomUrlHandlingStrategy implements UrlHandlingStrategy { + shouldProcessUrl(url: UrlTree): boolean { + // Only handle URLs that start with /app or /admin + return url.toString().startsWith('/app') || + url.toString().startsWith('/admin'); + } + + extract(url: UrlTree): UrlTree { + // Return the URL unchanged if we should process it + return url; + } + + merge(newUrlPart: UrlTree, rawUrl: UrlTree): UrlTree { + // Combine the URL fragment with the rest of the URL + return newUrlPart; + } +} +``` + +This strategy creates clear boundaries in the URL space. Angular handles `/app` and `/admin` paths while ignoring everything else. This pattern works well when migrating legacy applications where Angular controls specific sections while the legacy system maintains others. + +### Configuring a custom URL handling strategy + +You can register a custom strategy through Angular's dependency injection system: + +```ts +import { ApplicationConfig } from '@angular/core'; +import { provideRouter } from '@angular/router'; +import { UrlHandlingStrategy } from '@angular/router'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideRouter(routes), + { provide: UrlHandlingStrategy, useClass: CustomUrlHandlingStrategy } + ] +}; +``` + +## Custom route matchers + +By default, Angular's router iterates through routes in the order they're defined, attempting to match the URL path against each route's path pattern. It supports static segments, parameterized segments (`:id`), and wildcards (`**`). The first route that matches wins, and the router stops searching. + +When applications require more sophisticated matching logic based on runtime conditions, complex URL patterns, or other custom rules, custom matchers provide this flexibility without compromising the simplicity of standard routes. + +The router evaluates custom matchers during the route matching phase, before path matching occurs. When a matcher returns a successful match, it can also extract parameters from the URL, making them available to the activated component just like standard route parameters. + +### Creating a custom matcher + +A custom matcher is a function that receives URL segments and returns either a match result with consumed segments and parameters, or null to indicate no match. The matcher function runs before Angular evaluates the route's path property: + +```ts +import { Route, UrlSegment, UrlSegmentGroup, UrlMatchResult } from '@angular/router'; + +export function customMatcher( + segments: UrlSegment[], + group: UrlSegmentGroup, + route: Route +): UrlMatchResult | null { + // Matching logic here + if (matchSuccessful) { + return { + consumed: segments, + posParams: { + paramName: new UrlSegment('paramValue', {}) + } + }; + } + return null; +} +``` + +### Implementing version-based routing + +Consider an API documentation site that needs to route based on version numbers in the URL. Different versions might have different component structures or feature sets: + +```ts +import { Routes, UrlSegment, UrlMatchResult } from '@angular/router'; + +export function versionMatcher(segments: UrlSegment[]): UrlMatchResult | null { + // Match patterns like /v1/docs, /v2.1/docs, /v3.0.1/docs + if (segments.length >= 2 && segments[0].path.match(/^v\d+(\.\d+)*$/)) { + return { + consumed: segments.slice(0, 2), // Consume version and 'docs' + posParams: { + version: segments[0], // Make version available as a parameter + section: segments[1] // Make section available too + } + }; + } + return null; +} + +// Route configuration +export const routes: Routes = [ + { + matcher: versionMatcher, + component: DocumentationComponent + }, + { + path: 'latest/docs', + redirectTo: 'v3/docs' + } +]; +``` + +The component receives the extracted parameters through route inputs: + +```ts +import { Component, input, inject } from '@angular/core'; +import { resource } from '@angular/core'; + +@Component({ + selector: 'app-documentation', + template: ` + @if (documentation.isLoading()) { +
Loading documentation...
+ } @else if (documentation.error()) { +
Error loading documentation
+ } @else if (documentation.value(); as docs) { +
{{ docs.content }}
+ } + ` +}) +export class DocumentationComponent { + // Route parameters are automatically bound to signal inputs + version = input.required(); // Receives the version parameter + section = input.required(); // Receives the section parameter + + private docsService = inject(DocumentationService); + + // Resource automatically loads documentation when version or section changes + documentation = resource({ + params: () => { + if (!this.version() || !this.section()) return; + + return { + version: this.version(), + section: this.section() + } + }, + loader: ({ params }) => { + return this.docsService.loadDocumentation(params.version, params.section); + } + }) +} +``` + +### Locale-aware routing + +International applications often encode locale information in URLs. A custom matcher can extract locale codes and route to appropriate components while making the locale available as a parameter: + +```ts +// Supported locales +const locales = ['en', 'es', 'fr', 'de', 'ja', 'zh']; + +export function localeMatcher(segments: UrlSegment[]): UrlMatchResult | null { + if (segments.length > 0) { + const potentialLocale = segments[0].path; + + if (locales.includes(potentialLocale)) { + // This is a locale prefix, consume it and continue matching + return { + consumed: [segments[0]], + posParams: { + locale: segments[0] + } + }; + } else { + // No locale prefix, use default locale + return { + consumed: [], // Don't consume any segments + posParams: { + locale: new UrlSegment('en', {}) + } + }; + } + } + + return null; +} +``` + +### Complex business logic matching + +Custom matchers excel at implementing business rules that would be awkward to express in path patterns. Consider an e-commerce site where product URLs follow different patterns based on product type: + +```ts +export function productMatcher(segments: UrlSegment[]): UrlMatchResult | null { + if (segments.length === 0) return null; + + const firstSegment = segments[0].path; + + // Books: /isbn-1234567890 + if (firstSegment.startsWith('isbn-')) { + return { + consumed: [segments[0]], + posParams: { + productType: new UrlSegment('book', {}), + identifier: new UrlSegment(firstSegment.substring(5), {}) + } + }; + } + + // Electronics: /sku/ABC123 + if (firstSegment === 'sku' && segments.length > 1) { + return { + consumed: segments.slice(0, 2), + posParams: { + productType: new UrlSegment('electronics', {}), + identifier: segments[1] + } + }; + } + + // Clothing: /style/BRAND/ITEM + if (firstSegment === 'style' && segments.length > 2) { + return { + consumed: segments.slice(0, 3), + posParams: { + productType: new UrlSegment('clothing', {}), + brand: segments[1], + identifier: segments[2] + } + }; + } + + return null; +} +``` + +### Performance considerations for custom matchers + +Custom matchers run for every navigation attempt until a match is found. As a result, complex matching logic can impact navigation performance, especially in applications with many routes. Keep matchers focused and efficient: + +- Return early when a match is impossible +- Avoid expensive operations like API calls or complex regular expressions +- Consider caching results for repeated URL patterns + +While custom matchers solve complex routing requirements elegantly, overuse can make route configuration harder to understand and maintain. Reserve custom matchers for scenarios where standard path matching genuinely falls short. diff --git a/adev-es/src/content/guide/routing/customizing-route-behavior.md b/adev-es/src/content/guide/routing/customizing-route-behavior.md index 6ae475f..e4b9ca3 100644 --- a/adev-es/src/content/guide/routing/customizing-route-behavior.md +++ b/adev-es/src/content/guide/routing/customizing-route-behavior.md @@ -1,56 +1,56 @@ -# Customizing route behavior +# Personalizando el comportamiento de rutas -Angular Router provides powerful extension points that allow you to customize how routes behave in your application. While the default routing behavior works well for most applications, specific requirements often demand custom implementations for performance optimization, specialized URL handling, or complex routing logic. +Angular Router proporciona puntos de extensión poderosos que te permiten personalizar cómo se comportan las rutas en tu aplicación. Si bien el comportamiento de enrutamiento predeterminado funciona bien para la mayoría de las aplicaciones, requisitos específicos a menudo demandan implementaciones personalizadas para optimización del rendimiento, manejo especializado de URLs o lógica de enrutamiento compleja. -Route customization can become valuable when your application needs: +La personalización de rutas puede volverse valiosa cuando tu aplicación necesita: -- **Component state preservation** across navigations to avoid re-fetching data -- **Strategic lazy module loading** based on user behavior or network conditions -- **External URL integration** or handling Angular routes alongside legacy systems -- **Dynamic route matching** based on runtime conditions beyond simple path - patterns +- **Preservación del estado del componente** a través de navegaciones para evitar volver a obtener datos +- **Carga estratégica de módulos lazy** basada en el comportamiento del usuario o condiciones de red +- **Integración de URLs externas** o manejo de rutas de Angular junto con sistemas legacy +- **Coincidencia dinámica de rutas** basada en condiciones de tiempo de ejecución más allá de patrones de + ruta simples -NOTE: Before implementing custom strategies, ensure the default router behavior doesn't meet your needs. Angular's default routing is optimized for common use cases and provides the best balance of performance and simplicity. Customizing route strategies can create additional code complexity and have performance implications on memory usage if not carefully managed. +NOTA: Antes de implementar estrategias personalizadas, asegúrate de que el comportamiento predeterminado del router no satisfaga tus necesidades. El enrutamiento predeterminado en Angular está optimizado para casos de uso comunes y proporciona el mejor balance de rendimiento y simplicidad. Personalizar estrategias de ruta puede crear complejidad adicional en el código y tener implicaciones de rendimiento en el uso de memoria si no se gestiona cuidadosamente. -Angular Router exposes four main areas for customization: +Angular Router expone cuatro áreas principales para personalización: - - - - + + + + -## Route reuse strategy +## Estrategia de reutilización de rutas -Route reuse strategy controls whether Angular destroys and recreates components during navigation or preserves them for reuse. By default, Angular destroys component instances when navigating away from a route and creates new instances when navigating back. +La estrategia de reutilización de rutas controla si Angular destruye y recrea componentes durante la navegación o los preserva para reutilizarlos. Por defecto, Angular destruye instancias de componentes al navegar fuera de una ruta y crea nuevas instancias al navegar de regreso. -### When to implement route reuse +### Cuándo implementar reutilización de rutas -Custom route reuse strategies benefit applications that need: +Las estrategias personalizadas de reutilización de rutas benefician a aplicaciones que necesitan: -- **Form state preservation** - Keep partially completed forms when users navigate away and return -- **Expensive data retention** - Avoid re-fetching large datasets or complex calculations -- **Scroll position maintenance** - Preserve scroll positions in long lists or infinite scroll implementations -- **Tab-like interfaces** - Maintain component state when switching between tabs +- **Preservación del estado de formularios** - Mantener formularios parcialmente completados cuando los usuarios navegan fuera y regresan +- **Retención de datos costosos** - Evitar volver a obtener grandes conjuntos de datos o cálculos complejos +- **Mantenimiento de la posición del scroll** - Preservar posiciones de scroll en listas largas o implementaciones de scroll infinito +- **Interfaces tipo pestaña** - Mantener el estado del componente al cambiar entre pestañas -### Creating a custom route reuse strategy +### Creando una estrategia personalizada de reutilización de rutas -Angular's `RouteReuseStrategy` class allows you to customize navigation behavior through the concept of "detached route handles." +La clase `RouteReuseStrategy` de Angular te permite personalizar el comportamiento de navegación a través del concepto de "handles de ruta desconectados". -"Detached route handles" are Angular's way of storing component instances and their entire view hierarchy. When a route is detached, Angular preserves the component instance, its child components, and all associated state in memory. This preserved state can later be reattached when navigating back to the route. +Los "handles de ruta desconectados" son la forma de Angular de almacenar instancias de componentes y toda su jerarquía de vistas. Cuando una ruta se desconecta, Angular preserva la instancia del componente, sus componentes hijos y todo el estado asociado en memoria. Este estado preservado puede ser reconectado posteriormente al navegar de regreso a la ruta. -The `RouteReuseStrategy` class provides five methods that control the lifecycle of route components: +La clase `RouteReuseStrategy` proporciona cinco métodos que controlan el ciclo de vida de los componentes de ruta: -| Method | Description | -| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | -| [`shouldDetach`](api/router/RouteReuseStrategy#shouldDetach) | Determines if a route should be stored for later reuse when navigating away | -| [`store`](api/router/RouteReuseStrategy#store) | Stores the detached route handle when `shouldDetach` returns true | -| [`shouldAttach`](api/router/RouteReuseStrategy#shouldAttach) | Determines if a stored route should be reattached when navigating to it | -| [`retrieve`](api/router/RouteReuseStrategy#retrieve) | Returns the previously stored route handle for reattachment | -| [`shouldReuseRoute`](api/router/RouteReuseStrategy#shouldReuseRoute) | Determines if the router should reuse the current route instance instead of destroying it during navigation | +| Método | Descripción | +| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| [`shouldDetach`](api/router/RouteReuseStrategy#shouldDetach) | Determina si una ruta debe almacenarse para reutilización posterior al navegar fuera | +| [`store`](api/router/RouteReuseStrategy#store) | Almacena el handle de ruta desconectado cuando `shouldDetach` retorna true | +| [`shouldAttach`](api/router/RouteReuseStrategy#shouldAttach) | Determina si una ruta almacenada debe reconectarse al navegar a ella | +| [`retrieve`](api/router/RouteReuseStrategy#retrieve) | Retorna el handle de ruta previamente almacenado para reconexión | +| [`shouldReuseRoute`](api/router/RouteReuseStrategy#shouldReuseRoute) | Determina si el router debe reutilizar la instancia de ruta actual en lugar de destruirla durante la navegación | -The following example demonstrates a custom route reuse strategy that selectively preserves component state based on route metadata: +El siguiente ejemplo demuestra una estrategia personalizada de reutilización de rutas que preserva selectivamente el estado del componente basado en metadatos de ruta: ```ts import { RouteReuseStrategy, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router'; @@ -61,12 +61,12 @@ export class CustomRouteReuseStrategy implements RouteReuseStrategy { private handlers = new Map(); shouldDetach(route: ActivatedRouteSnapshot): boolean { - // Determines if a route should be stored for later reuse + // Determina si una ruta debe almacenarse para reutilización posterior return route.data['reuse'] === true; } store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle | null): void { - // Stores the detached route handle when shouldDetach returns true + // Almacena el handle de ruta desconectado cuando shouldDetach retorna true if (handle && route.data['reuse'] === true) { const key = this.getRouteKey(route); this.handlers.set(key, handle); @@ -74,19 +74,19 @@ export class CustomRouteReuseStrategy implements RouteReuseStrategy { } shouldAttach(route: ActivatedRouteSnapshot): boolean { - // Checks if a stored route should be reattached + // Verifica si una ruta almacenada debe reconectarse const key = this.getRouteKey(route); return route.data['reuse'] === true && this.handlers.has(key); } retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null { - // Returns the stored route handle for reattachment + // Retorna el handle de ruta almacenado para reconexión const key = this.getRouteKey(route); return route.data['reuse'] === true ? this.handlers.get(key) ?? null : null; } shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { - // Determines if the router should reuse the current route instance + // Determina si el router debe reutilizar la instancia de ruta actual return future.routeConfig === curr.routeConfig; } @@ -96,31 +96,31 @@ export class CustomRouteReuseStrategy implements RouteReuseStrategy { } ``` -### Configuring a route to use a custom route reuse strategy +### Configurando una ruta para usar una estrategia personalizada de reutilización -Routes can opt into reuse behavior through route configuration metadata. This approach keeps the reuse logic separate from component code, making it easy to adjust behavior without modifying components: +Las rutas pueden optar por el comportamiento de reutilización a través de metadatos de configuración de ruta. Este enfoque mantiene la lógica de reutilización separada del código del componente, facilitando el ajuste del comportamiento sin modificar componentes: ```ts export const routes: Routes = [ { path: 'products', component: ProductListComponent, - data: { reuse: true } // Component state persists across navigations + data: { reuse: true } // El estado del componente persiste a través de navegaciones }, { path: 'products/:id', component: ProductDetailComponent, - // No reuse flag - component recreates on each navigation + // Sin flag de reutilización - el componente se recrea en cada navegación }, { path: 'search', component: SearchComponent, - data: { reuse: true } // Preserves search results and filter state + data: { reuse: true } // Preserva resultados de búsqueda y estado de filtros } ]; ``` -You can also configure a custom route reuse strategy at the application level through Angular's dependency injection system. In this case, Angular creates a single instance of the strategy that manages all route reuse decisions throughout the application: +También puedes configurar una estrategia personalizada de reutilización de rutas a nivel de aplicación a través del sistema de inyección de dependencias de Angular. En este caso, Angular crea una única instancia de la estrategia que gestiona todas las decisiones de reutilización de rutas en toda la aplicación: ```ts export const appConfig: ApplicationConfig = { @@ -131,20 +131,20 @@ export const appConfig: ApplicationConfig = { }; ``` -## Preloading strategy +## Estrategia de precarga -Preloading strategies determine when Angular loads lazy-loaded route modules in the background. While lazy loading improves initial load time by deferring module downloads, users still experience a delay when first navigating to a lazy route. Preloading strategies eliminate this delay by loading modules before users request them. +Las estrategias de precarga determinan cuándo Angular carga módulos de ruta con lazy loading en segundo plano. Si bien el lazy loading mejora el tiempo de carga inicial al diferir las descargas de módulos, los usuarios aún experimentan un retraso al navegar por primera vez a una ruta lazy. Las estrategias de precarga eliminan este retraso cargando módulos antes de que los usuarios los soliciten. -### Built-in preloading strategies +### Estrategias de precarga integradas -Angular provides two preloading strategies out of the box: +Angular proporciona dos estrategias de precarga listas para usar: -| Strategy | Description | -| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | -| [`NoPreloading`](api/router/NoPreloading) | The default strategy that disables all preloading. In other words, modules only load when users navigate to them | -| [`PreloadAllModules`](api/router/PreloadAllModules) | Loads all lazy-loaded modules immediately after the initial navigation | +| Estrategia | Descripción | +| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| [`NoPreloading`](api/router/NoPreloading) | La estrategia predeterminada que deshabilita toda precarga. En otras palabras, los módulos solo se cargan cuando los usuarios navegan a ellos | +| [`PreloadAllModules`](api/router/PreloadAllModules) | Carga todos los módulos con lazy loading inmediatamente después de la navegación inicial | -The `PreloadAllModules` strategy can be configured as follows: +La estrategia `PreloadAllModules` puede configurarse de la siguiente manera: ```ts import { ApplicationConfig } from '@angular/core'; @@ -161,11 +161,11 @@ export const appConfig: ApplicationConfig = { }; ``` -The `PreloadAllModules` strategy works well for small to medium applications where downloading all modules doesn't significantly impact performance. However, larger applications with many feature modules might benefit from more selective preloading. +La estrategia `PreloadAllModules` funciona bien para aplicaciones pequeñas a medianas donde descargar todos los módulos no impacta significativamente el rendimiento. Sin embargo, las aplicaciones más grandes con muchos módulos de características podrían beneficiarse de una precarga más selectiva. -### Creating a custom preloading strategy +### Creando una estrategia de precarga personalizada -Custom preloading strategies implement the `PreloadingStrategy` interface, which requires a single `preload` method. This method receives the route configuration and a function that triggers the actual module load. The strategy returns an Observable that emits when preloading completes or an empty Observable to skip preloading: +Las estrategias personalizadas de precarga implementan la interfaz `PreloadingStrategy`, que requiere un único método `preload`. Este método recibe la configuración de ruta y una función que dispara la carga real del módulo. La estrategia retorna un Observable que emite cuando la precarga se completa o un Observable vacío para omitir la precarga: ```ts import { Injectable } from '@angular/core'; @@ -176,7 +176,7 @@ import { mergeMap } from 'rxjs/operators'; @Injectable() export class SelectivePreloadingStrategy implements PreloadingStrategy { preload(route: Route, load: () => Observable): Observable { - // Only preload routes marked with data: { preload: true } + // Solo precargar rutas marcadas con data: { preload: true } if (route.data?.['preload']) { return load(); } @@ -185,7 +185,7 @@ export class SelectivePreloadingStrategy implements PreloadingStrategy { } ``` -This selective strategy checks route metadata to determine preloading behavior. Routes can opt into preloading through their configuration: +Esta estrategia selectiva verifica los metadatos de ruta para determinar el comportamiento de precarga. Las rutas pueden optar por la precarga a través de su configuración: ```ts import { Routes } from '@angular/router'; @@ -194,38 +194,38 @@ export const routes: Routes = [ { path: 'dashboard', loadChildren: () => import('./dashboard/dashboard.routes'), - data: { preload: true } // Preload immediately after initial navigation + data: { preload: true } // Precargar inmediatamente después de la navegación inicial }, { path: 'reports', loadChildren: () => import('./reports/reports.routes'), - data: { preload: false } // Only load when user navigates to reports + data: { preload: false } // Solo cargar cuando el usuario navega a reports }, { path: 'admin', loadChildren: () => import('./admin/admin.routes') - // No preload flag - won't be preloaded + // Sin flag de precarga - no se precargará } ]; ``` -### Performance considerations for preloading +### Consideraciones de rendimiento para la precarga -Preloading impacts both network usage and memory consumption. Each preloaded module consumes bandwidth and increases the application's memory footprint. Mobile users on metered connections might prefer minimal preloading, while desktop users on fast networks can handle aggressive preloading strategies. +La precarga impacta tanto el uso de red como el consumo de memoria. Cada módulo precargado consume ancho de banda y aumenta la huella de memoria de la aplicación. Los usuarios móviles con conexiones medidas podrían preferir una precarga mínima, mientras que los usuarios de escritorio en redes rápidas pueden manejar estrategias de precarga agresivas. -The timing of preloading also matters. Immediate preloading after initial load might compete with other critical resources like images or API calls. Strategies should consider the application's post-load behavior and coordinate with other background tasks to avoid performance degradation. +El timing de la precarga también importa. La precarga inmediata después de la carga inicial podría competir con otros recursos críticos como imágenes o llamadas a API. Las estrategias deberían considerar el comportamiento post-carga de la aplicación y coordinarse con otras tareas en segundo plano para evitar la degradación del rendimiento. -Browser resource limits also affect preloading behavior. Browsers limit concurrent HTTP connections, so aggressive preloading might queue behind other requests. Service workers can help by providing fine-grained control over caching and network requests, complementing the preloading strategy. +Los límites de recursos del navegador también afectan el comportamiento de precarga. Los navegadores limitan las conexiones HTTP concurrentes, por lo que la precarga agresiva podría hacer cola detrás de otras peticiones. Los service workers pueden ayudar proporcionando control detallado sobre el almacenamiento en caché y las peticiones de red, complementando la estrategia de precarga. -## URL handling strategy +## Estrategia de manejo de URL -URL handling strategies determine which URLs the Angular router processes versus which ones it ignores. By default, Angular attempts to handle all navigation events within the application, but real-world applications often need to coexist with other systems, handle external links, or integrate with legacy applications that manage their own routes. +Las estrategias de manejo de URL determinan qué URLs procesa el router de Angular versus cuáles ignora. Por defecto, Angular intenta manejar todos los eventos de navegación dentro de la aplicación, pero las aplicaciones del mundo real a menudo necesitan coexistir con otros sistemas, manejar enlaces externos o integrarse con aplicaciones legacy que gestionan sus propias rutas. -The `UrlHandlingStrategy` class gives you control over this boundary between Angular-managed routes and external URLs. This becomes essential when migrating applications to Angular incrementally or when Angular applications need to share URL space with other frameworks. +La clase `UrlHandlingStrategy` te da control sobre este límite entre rutas gestionadas por Angular y URLs externas. Esto se vuelve esencial al migrar aplicaciones a Angular de forma incremental o cuando las aplicaciones Angular necesitan compartir espacio de URL con otros frameworks. -### Implementing a custom URL handling strategy +### Implementando una estrategia personalizada de manejo de URL -Custom URL handling strategies extend the `UrlHandlingStrategy` class and implement three methods. The `shouldProcessUrl` method determines whether Angular should handle a given URL, `extract` returns the portion of the URL that Angular should process, and `merge` combines the URL fragment with the rest of the URL: +Las estrategias personalizadas de manejo de URL extienden la clase `UrlHandlingStrategy` e implementan tres métodos. El método `shouldProcessUrl` determina si Angular debe manejar una URL dada, `extract` retorna la porción de la URL que Angular debe procesar, y `merge` combina el fragmento de URL con el resto de la URL: ```ts import { Injectable } from '@angular/core'; @@ -234,28 +234,28 @@ import { UrlHandlingStrategy, UrlTree } from '@angular/router'; @Injectable() export class CustomUrlHandlingStrategy implements UrlHandlingStrategy { shouldProcessUrl(url: UrlTree): boolean { - // Only handle URLs that start with /app or /admin + // Solo manejar URLs que comienzan con /app o /admin return url.toString().startsWith('/app') || url.toString().startsWith('/admin'); } extract(url: UrlTree): UrlTree { - // Return the URL unchanged if we should process it + // Retornar la URL sin cambios si debemos procesarla return url; } merge(newUrlPart: UrlTree, rawUrl: UrlTree): UrlTree { - // Combine the URL fragment with the rest of the URL + // Combinar el fragmento de URL con el resto de la URL return newUrlPart; } } ``` -This strategy creates clear boundaries in the URL space. Angular handles `/app` and `/admin` paths while ignoring everything else. This pattern works well when migrating legacy applications where Angular controls specific sections while the legacy system maintains others. +Esta estrategia crea límites claros en el espacio de URL. Angular maneja rutas `/app` y `/admin` mientras ignora todo lo demás. Este patrón funciona bien al migrar aplicaciones legacy donde Angular controla secciones específicas mientras el sistema legacy mantiene otras. -### Configuring a custom URL handling strategy +### Configurando una estrategia personalizada de manejo de URL -You can register a custom strategy through Angular's dependency injection system: +Puedes registrar una estrategia personalizada a través del sistema de inyección de dependencias de Angular: ```ts import { ApplicationConfig } from '@angular/core'; @@ -270,17 +270,17 @@ export const appConfig: ApplicationConfig = { }; ``` -## Custom route matchers +## Matchers de ruta personalizados -By default, Angular's router iterates through routes in the order they're defined, attempting to match the URL path against each route's path pattern. It supports static segments, parameterized segments (`:id`), and wildcards (`**`). The first route that matches wins, and the router stops searching. +Por defecto, el router de Angular itera a través de las rutas en el orden en que están definidas, intentando hacer coincidir la ruta URL contra el patrón de ruta de cada ruta. Soporta segmentos estáticos, segmentos parametrizados (`:id`) y comodines (`**`). La primera ruta que coincide gana, y el router deja de buscar. -When applications require more sophisticated matching logic based on runtime conditions, complex URL patterns, or other custom rules, custom matchers provide this flexibility without compromising the simplicity of standard routes. +Cuando las aplicaciones requieren lógica de coincidencia más sofisticada basada en condiciones de tiempo de ejecución, patrones de URL complejos u otras reglas personalizadas, los matchers personalizados proporcionan esta flexibilidad sin comprometer la simplicidad de las rutas estándar. -The router evaluates custom matchers during the route matching phase, before path matching occurs. When a matcher returns a successful match, it can also extract parameters from the URL, making them available to the activated component just like standard route parameters. +El router evalúa los matchers personalizados durante la fase de coincidencia de rutas, antes de que ocurra la coincidencia de rutas. Cuando un matcher retorna una coincidencia exitosa, también puede extraer parámetros de la URL, haciéndolos disponibles al componente activado al igual que los parámetros de ruta estándar. -### Creating a custom matcher +### Creando un matcher personalizado -A custom matcher is a function that receives URL segments and returns either a match result with consumed segments and parameters, or null to indicate no match. The matcher function runs before Angular evaluates the route's path property: +Un matcher personalizado es una función que recibe segmentos de URL y retorna ya sea un resultado de coincidencia con segmentos consumidos y parámetros, o null para indicar que no hay coincidencia. La función matcher se ejecuta antes de que Angular evalúe la propiedad path de la ruta: ```ts import { Route, UrlSegment, UrlSegmentGroup, UrlMatchResult } from '@angular/router'; @@ -290,7 +290,7 @@ export function customMatcher( group: UrlSegmentGroup, route: Route ): UrlMatchResult | null { - // Matching logic here + // Lógica de coincidencia aquí if (matchSuccessful) { return { consumed: segments, @@ -303,28 +303,28 @@ export function customMatcher( } ``` -### Implementing version-based routing +### Implementando enrutamiento basado en versiones -Consider an API documentation site that needs to route based on version numbers in the URL. Different versions might have different component structures or feature sets: +Considera un sitio de documentación de API que necesita enrutar basándose en números de versión en la URL. Diferentes versiones podrían tener diferentes estructuras de componentes o conjuntos de características: ```ts import { Routes, UrlSegment, UrlMatchResult } from '@angular/router'; export function versionMatcher(segments: UrlSegment[]): UrlMatchResult | null { - // Match patterns like /v1/docs, /v2.1/docs, /v3.0.1/docs + // Hacer coincidir patrones como /v1/docs, /v2.1/docs, /v3.0.1/docs if (segments.length >= 2 && segments[0].path.match(/^v\d+(\.\d+)*$/)) { return { - consumed: segments.slice(0, 2), // Consume version and 'docs' + consumed: segments.slice(0, 2), // Consumir versión y 'docs' posParams: { - version: segments[0], // Make version available as a parameter - section: segments[1] // Make section available too + version: segments[0], // Hacer la versión disponible como parámetro + section: segments[1] // Hacer la sección disponible también } }; } return null; } -// Route configuration +// Configuración de rutas export const routes: Routes = [ { matcher: versionMatcher, @@ -337,7 +337,7 @@ export const routes: Routes = [ ]; ``` -The component receives the extracted parameters through route inputs: +El componente recibe los parámetros extraídos a través de inputs de ruta: ```ts import { Component, input, inject } from '@angular/core'; @@ -347,22 +347,22 @@ import { resource } from '@angular/core'; selector: 'app-documentation', template: ` @if (documentation.isLoading()) { -
Loading documentation...
+
Cargando documentación...
} @else if (documentation.error()) { -
Error loading documentation
+
Error al cargar documentación
} @else if (documentation.value(); as docs) {
{{ docs.content }}
} ` }) export class DocumentationComponent { - // Route parameters are automatically bound to signal inputs - version = input.required(); // Receives the version parameter - section = input.required(); // Receives the section parameter + // Los parámetros de ruta se vinculan automáticamente a signal inputs + version = input.required(); // Recibe el parámetro version + section = input.required(); // Recibe el parámetro section private docsService = inject(DocumentationService); - // Resource automatically loads documentation when version or section changes + // Resource carga automáticamente documentación cuando version o section cambian documentation = resource({ params: () => { if (!this.version() || !this.section()) return; @@ -379,12 +379,12 @@ export class DocumentationComponent { } ``` -### Locale-aware routing +### Enrutamiento consciente de locale -International applications often encode locale information in URLs. A custom matcher can extract locale codes and route to appropriate components while making the locale available as a parameter: +Las aplicaciones internacionales a menudo codifican información de locale en URLs. Un matcher personalizado puede extraer códigos de locale y enrutar a componentes apropiados mientras hace el locale disponible como parámetro: ```ts -// Supported locales +// Locales soportados const locales = ['en', 'es', 'fr', 'de', 'ja', 'zh']; export function localeMatcher(segments: UrlSegment[]): UrlMatchResult | null { @@ -392,7 +392,7 @@ export function localeMatcher(segments: UrlSegment[]): UrlMatchResult | null { const potentialLocale = segments[0].path; if (locales.includes(potentialLocale)) { - // This is a locale prefix, consume it and continue matching + // Esto es un prefijo de locale, consumirlo y continuar coincidiendo return { consumed: [segments[0]], posParams: { @@ -400,9 +400,9 @@ export function localeMatcher(segments: UrlSegment[]): UrlMatchResult | null { } }; } else { - // No locale prefix, use default locale + // Sin prefijo de locale, usar locale predeterminado return { - consumed: [], // Don't consume any segments + consumed: [], // No consumir ningún segmento posParams: { locale: new UrlSegment('en', {}) } @@ -414,9 +414,9 @@ export function localeMatcher(segments: UrlSegment[]): UrlMatchResult | null { } ``` -### Complex business logic matching +### Coincidencia de lógica de negocio compleja -Custom matchers excel at implementing business rules that would be awkward to express in path patterns. Consider an e-commerce site where product URLs follow different patterns based on product type: +Los matchers personalizados sobresalen en implementar reglas de negocio que serían incómodas de expresar en patrones de ruta. Considera un sitio de comercio electrónico donde las URLs de productos siguen diferentes patrones basados en el tipo de producto: ```ts export function productMatcher(segments: UrlSegment[]): UrlMatchResult | null { @@ -424,7 +424,7 @@ export function productMatcher(segments: UrlSegment[]): UrlMatchResult | null { const firstSegment = segments[0].path; - // Books: /isbn-1234567890 + // Libros: /isbn-1234567890 if (firstSegment.startsWith('isbn-')) { return { consumed: [segments[0]], @@ -435,7 +435,7 @@ export function productMatcher(segments: UrlSegment[]): UrlMatchResult | null { }; } - // Electronics: /sku/ABC123 + // Electrónicos: /sku/ABC123 if (firstSegment === 'sku' && segments.length > 1) { return { consumed: segments.slice(0, 2), @@ -446,7 +446,7 @@ export function productMatcher(segments: UrlSegment[]): UrlMatchResult | null { }; } - // Clothing: /style/BRAND/ITEM + // Ropa: /style/BRAND/ITEM if (firstSegment === 'style' && segments.length > 2) { return { consumed: segments.slice(0, 3), @@ -462,12 +462,12 @@ export function productMatcher(segments: UrlSegment[]): UrlMatchResult | null { } ``` -### Performance considerations for custom matchers +### Consideraciones de rendimiento para matchers personalizados -Custom matchers run for every navigation attempt until a match is found. As a result, complex matching logic can impact navigation performance, especially in applications with many routes. Keep matchers focused and efficient: +Los matchers personalizados se ejecutan para cada intento de navegación hasta que se encuentra una coincidencia. Como resultado, la lógica de coincidencia compleja puede impactar el rendimiento de navegación, especialmente en aplicaciones con muchas rutas. Mantén los matchers enfocados y eficientes: -- Return early when a match is impossible -- Avoid expensive operations like API calls or complex regular expressions -- Consider caching results for repeated URL patterns +- Retorna temprano cuando una coincidencia es imposible +- Evita operaciones costosas como llamadas a API o expresiones regulares complejas +- Considera almacenar en caché resultados para patrones de URL repetidos -While custom matchers solve complex routing requirements elegantly, overuse can make route configuration harder to understand and maintain. Reserve custom matchers for scenarios where standard path matching genuinely falls short. +Si bien los matchers personalizados resuelven requisitos de enrutamiento complejos de manera elegante, el uso excesivo puede hacer que la configuración de rutas sea más difícil de entender y mantener. Reserva los matchers personalizados para escenarios donde la coincidencia de rutas estándar realmente se queda corta. diff --git a/adev-es/src/content/guide/routing/data-resolvers.en.md b/adev-es/src/content/guide/routing/data-resolvers.en.md new file mode 100644 index 0000000..4407598 --- /dev/null +++ b/adev-es/src/content/guide/routing/data-resolvers.en.md @@ -0,0 +1,298 @@ +# Data resolvers + +Data resolvers allow you to fetch data before navigating to a route, ensuring that your components receive the data they need before rendering. This can help prevent the need for loading states and improve the user experience by pre-loading essential data. + +## What are data resolvers? + +A data resolver is a service that implements the [`ResolveFn`](api/router/ResolveFn) function. It runs before a route activates and can fetch data from APIs, databases, or other sources. The resolved data becomes available to the component through the [`ActivatedRoute`](api/router/ActivatedRoute). + +## Why use data resolvers? + +Data resolvers solve common routing challenges: + +- **Prevent empty states**: Components receive data immediately upon loading +- **Better user experience**: No loading spinners for critical data +- **Error handling**: Handle data fetching errors before navigation +- **Data consistency**: Ensure required data is available before rendering which is important for SSR + +## Creating a resolver + +You create a resolver by writing a function with the [`ResolveFn`](api/router/ResolveFn) type. + +It receives the [`ActivatedRouteSnapshot`](api/router/ActivatedRouteSnapshot) and [`RouterStateSnapshot`](api/router/RouterStateSnapshot) as parameters. + +Here is a resolver that gets the user information before rendering a route using the [`inject`](api/core/inject) function: + +```ts +import { inject } from '@angular/core'; +import { UserStore, SettingsStore } from './user-store'; +import type { ActivatedRouteSnapshot, ResolveFn, RouterStateSnapshot } from '@angular/router'; +import type { User, Settings } from './types'; + +export const userResolver: ResolveFn = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { + const userStore = inject(UserStore); + const userId = route.paramMap.get('id')!; + return userStore.getUser(userId); +}; + +export const settingsResolver: ResolveFn = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { + const settingsStore = inject(SettingsStore); + const userId = route.paramMap.get('id')!; + return settingsStore.getUserSettings(userId); +}; +``` + +## Configuring routes with resolvers + +When you want to add one or more data resolvers to a route, you can add it under the `resolve` key in the route configuration. The [`Routes`](api/router/Routes) type defines the structure for route configurations: + +```ts +import { Routes } from '@angular/router'; + +export const routes: Routes = [ + { + path: 'user/:id', + component: UserDetail, + resolve: { + user: userResolver, + settings: settingsResolver + } + } +]; +``` + +You can learn more about the [`resolve` configuration in the API docs](api/router/Route#resolve). + +## Accessing resolved data in components + +### Using ActivatedRoute + +You can access the resolved data in a component by accessing the snapshot data from the [`ActivatedRoute`](api/router/ActivatedRoute) using the [`signal`](api/core/signal) function: + +```angular-ts +import { Component, inject, computed } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { toSignal } from '@angular/core/rxjs-interop'; +import type { User, Settings } from './types'; + +@Component({ + template: ` +

{{ user().name }}

+

{{ user().email }}

+
Theme: {{ settings().theme }}
+ ` +}) +export class UserDetail { + private route = inject(ActivatedRoute); + private data = toSignal(this.route.data); + user = computed(() => this.data().user as User); + settings = computed(() => this.data().settings as Settings); +} +``` + +### Using withComponentInputBinding + +A different approach to accessing the resolved data is to use [`withComponentInputBinding()`](api/router/withComponentInputBinding) when configuring your router with [`provideRouter`](api/router/provideRouter). This allows resolved data to be passed directly as component inputs: + +```ts +import { bootstrapApplication } from '@angular/platform-browser'; +import { provideRouter, withComponentInputBinding } from '@angular/router'; +import { routes } from './app.routes'; + +bootstrapApplication(App, { + providers: [ + provideRouter(routes, withComponentInputBinding()) + ] +}); +``` + +With this configuration, you can define inputs in your component that match the resolver keys using the [`input`](api/core/input) function and [`input.required`](api/core/input#required) for required inputs: + +```angular-ts +import { Component, input } from '@angular/core'; +import type { User, Settings } from './types'; + +@Component({ + template: ` +

{{ user().name }}

+

{{ user().email }}

+
Theme: {{ settings().theme }}
+ ` +}) +export class UserDetail { + user = input.required(); + settings = input.required(); +} +``` + +This approach provides better type safety and eliminates the need to inject `ActivatedRoute` just to access resolved data. + +## Error handling in resolvers + +In the event of navigation failures, it is important to handle errors gracefully in your data resolvers. Otherwise, a `NavigationError` will occur and the navigation to the current route will fail which will lead to a poor experience for your users. + +There are three primary ways to handle errors with data resolvers: + +1. [Centralizing error handling in `withNavigationErrorHandler`](#centralize-error-handling-in-withnavigationerrorhandler) +2. [Managing errors through a subscription to router events](#managing-errors-through-a-subscription-to-router-events) +3. [Handling errors directly in the resolver](#handling-errors-directly-in-the-resolver) + +### Centralize error handling in `withNavigationErrorHandler` + +The [`withNavigationErrorHandler`](api/router/withNavigationErrorHandler) feature provides a centralized way to handle all navigation errors, including those from failed data resolvers. This approach keeps error handling logic in one place and prevents duplicate error handling code across resolvers. + +```ts +import { bootstrapApplication } from '@angular/platform-browser'; +import { provideRouter, withNavigationErrorHandler } from '@angular/router'; +import { inject } from '@angular/core'; +import { Router } from '@angular/router'; +import { routes } from './app.routes'; + +bootstrapApplication(App, { + providers: [ + provideRouter(routes, withNavigationErrorHandler((error) => { + const router = inject(Router); + + if (error?.message) { + console.error('Navigation error occurred:', error.message) + } + + router.navigate(['/error']); + })) + ] +}); +``` + +With this configuration, your resolvers can focus on data fetching while letting the centralized handler manage error scenarios: + +```ts +export const userResolver: ResolveFn = (route) => { + const userStore = inject(UserStore); + const userId = route.paramMap.get('id')!; + // No need for explicit error handling - let it bubble up + return userStore.getUser(userId); +}; +``` + +### Managing errors through a subscription to router events + +You can also handle resolver errors by subscribing to router events and listening for [`NavigationError`](api/router/NavigationError) events. This approach gives you more granular control over error handling and allows you to implement custom error recovery logic. + +```angular-ts +import { Component, inject, signal } from '@angular/core'; +import { Router, NavigationError } from '@angular/router'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { filter, map } from 'rxjs'; + +@Component({ + selector: 'app-root', + template: ` + @if (errorMessage()) { +
+ {{ errorMessage() }} + +
+ } + + ` +}) +export class App { + private router = inject(Router); + private lastFailedUrl = signal(''); + + private navigationErrors = toSignal( + this.router.events.pipe( + filter((event): event is NavigationError => event instanceof NavigationError), + map(event => { + this.lastFailedUrl.set(event.url); + + if (event.error) { + console.error('Navigation error', event.error) + } + + return 'Navigation failed. Please try again.'; + }) + ), + { initialValue: '' } + ); + + errorMessage = this.navigationErrors; + + retryNavigation() { + if (this.lastFailedUrl()) { + this.router.navigateByUrl(this.lastFailedUrl()); + } + } +} +``` + +This approach is particularly useful when you need to: + +- Implement custom retry logic for failed navigation +- Show specific error messages based on the type of failure +- Track navigation failures for analytics purposes + +### Handling errors directly in the resolver + +Here's an updated example of the `userResolver` that logs the error and navigates back to the generic `/users` page using the [`Router`](api/router/Router) service: + +```ts +import { inject } from '@angular/core'; +import { ResolveFn, RedirectCommand, Router } from '@angular/router'; +import { catchError, of, EMPTY } from 'rxjs'; +import { UserStore } from './user-store'; +import type { User } from './types'; + +export const userResolver: ResolveFn = (route) => { + const userStore = inject(UserStore); + const router = inject(Router); + const userId = route.paramMap.get('id')!; + + return userStore.getUser(userId).pipe( + catchError(error => { + console.error('Failed to load user:', error); + return of(new RedirectCommand(router.parseUrl('/users'))); + }) + ); +}; +``` + +## Navigation loading considerations + +While data resolvers prevent loading states within components, they introduce a different UX consideration: navigation is blocked while resolvers execute. Users may experience delays between clicking a link and seeing the new route, especially with slow network requests. + +### Providing navigation feedback + +To improve user experience during resolver execution, you can listen to router events and show loading indicators: + +```angular-ts +import { Component, inject } from '@angular/core'; +import { Router } from '@angular/router'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { map } from 'rxjs'; + +@Component({ + selector: 'app-root', + template: ` + @if (isNavigating()) { +
Loading...
+ } + + ` +}) +export class App { + private router = inject(Router); + isNavigating = computed(() => !!this.router.currentNavigation()); +} +``` + +This approach ensures users receive visual feedback that navigation is in progress while resolvers fetch data. + +## Best practices + +- **Keep resolvers lightweight**: Resolvers should fetch essential data only and not everything the page could possibly need +- **Handle errors**: Always remember to handle errors gracefully to provide the best experience possible to users +- **Use caching**: Consider caching resolved data to improve performance +- **Consider navigation UX**: Implement loading indicators for resolver execution since navigation is blocked during data fetching +- **Set reasonable timeouts**: Avoid resolvers that could hang indefinitely and block navigation +- **Type safety**: Use TypeScript interfaces for resolved data diff --git a/adev-es/src/content/guide/routing/data-resolvers.md b/adev-es/src/content/guide/routing/data-resolvers.md index 4407598..7f3c48a 100644 --- a/adev-es/src/content/guide/routing/data-resolvers.md +++ b/adev-es/src/content/guide/routing/data-resolvers.md @@ -1,27 +1,27 @@ # Data resolvers -Data resolvers allow you to fetch data before navigating to a route, ensuring that your components receive the data they need before rendering. This can help prevent the need for loading states and improve the user experience by pre-loading essential data. +Los data resolvers te permiten obtener datos antes de navegar a una ruta, asegurando que tus componentes reciban los datos que necesitan antes de renderizar. Esto puede ayudar a prevenir la necesidad de estados de carga y mejorar la experiencia del usuario al precargar datos esenciales. -## What are data resolvers? +## ¿Qué son los data resolvers? -A data resolver is a service that implements the [`ResolveFn`](api/router/ResolveFn) function. It runs before a route activates and can fetch data from APIs, databases, or other sources. The resolved data becomes available to the component through the [`ActivatedRoute`](api/router/ActivatedRoute). +Un data resolver es un servicio que implementa la función [`ResolveFn`](api/router/ResolveFn). Se ejecuta antes de que una ruta se active y puede obtener datos de APIs, bases de datos u otras fuentes. Los datos resueltos se vuelven disponibles para el componente a través del [`ActivatedRoute`](api/router/ActivatedRoute). -## Why use data resolvers? +## ¿Por qué usar data resolvers? -Data resolvers solve common routing challenges: +Los data resolvers resuelven desafíos comunes de enrutamiento: -- **Prevent empty states**: Components receive data immediately upon loading -- **Better user experience**: No loading spinners for critical data -- **Error handling**: Handle data fetching errors before navigation -- **Data consistency**: Ensure required data is available before rendering which is important for SSR +- **Prevenir estados vacíos**: Los componentes reciben datos inmediatamente al cargar +- **Mejor experiencia de usuario**: Sin spinners de carga para datos críticos +- **Manejo de errores**: Manejar errores de obtención de datos antes de la navegación +- **Consistencia de datos**: Asegurar que los datos requeridos estén disponibles antes de renderizar, lo cual es importante para SSR -## Creating a resolver +## Creando un resolver -You create a resolver by writing a function with the [`ResolveFn`](api/router/ResolveFn) type. +Creas un resolver escribiendo una función con el tipo [`ResolveFn`](api/router/ResolveFn). -It receives the [`ActivatedRouteSnapshot`](api/router/ActivatedRouteSnapshot) and [`RouterStateSnapshot`](api/router/RouterStateSnapshot) as parameters. +Recibe el [`ActivatedRouteSnapshot`](api/router/ActivatedRouteSnapshot) y el [`RouterStateSnapshot`](api/router/RouterStateSnapshot) como parámetros. -Here is a resolver that gets the user information before rendering a route using the [`inject`](api/core/inject) function: +Aquí hay un resolver que obtiene la información del usuario antes de renderizar una ruta usando la función [`inject`](api/core/inject): ```ts import { inject } from '@angular/core'; @@ -42,9 +42,9 @@ export const settingsResolver: ResolveFn = (route: ActivatedRouteSnaps }; ``` -## Configuring routes with resolvers +## Configurando rutas con resolvers -When you want to add one or more data resolvers to a route, you can add it under the `resolve` key in the route configuration. The [`Routes`](api/router/Routes) type defines the structure for route configurations: +Cuando quieres agregar uno o más data resolvers a una ruta, puedes agregarlo bajo la clave `resolve` en la configuración de ruta. El tipo [`Routes`](api/router/Routes) define la estructura para las configuraciones de ruta: ```ts import { Routes } from '@angular/router'; @@ -61,13 +61,13 @@ export const routes: Routes = [ ]; ``` -You can learn more about the [`resolve` configuration in the API docs](api/router/Route#resolve). +Puedes aprender más sobre la [configuración de `resolve` en los docs de la API](api/router/Route#resolve). -## Accessing resolved data in components +## Accediendo a datos resueltos en componentes -### Using ActivatedRoute +### Usando ActivatedRoute -You can access the resolved data in a component by accessing the snapshot data from the [`ActivatedRoute`](api/router/ActivatedRoute) using the [`signal`](api/core/signal) function: +Puedes acceder a los datos resueltos en un componente accediendo a los datos del snapshot desde el [`ActivatedRoute`](api/router/ActivatedRoute) usando la función [`signal`](api/core/signal): ```angular-ts import { Component, inject, computed } from '@angular/core'; @@ -90,9 +90,9 @@ export class UserDetail { } ``` -### Using withComponentInputBinding +### Usando withComponentInputBinding -A different approach to accessing the resolved data is to use [`withComponentInputBinding()`](api/router/withComponentInputBinding) when configuring your router with [`provideRouter`](api/router/provideRouter). This allows resolved data to be passed directly as component inputs: +Un enfoque diferente para acceder a los datos resueltos es usar [`withComponentInputBinding()`](api/router/withComponentInputBinding) al configurar tu router con [`provideRouter`](api/router/provideRouter). Esto permite que los datos resueltos se pasen directamente como inputs de componente: ```ts import { bootstrapApplication } from '@angular/platform-browser'; @@ -106,7 +106,7 @@ bootstrapApplication(App, { }); ``` -With this configuration, you can define inputs in your component that match the resolver keys using the [`input`](api/core/input) function and [`input.required`](api/core/input#required) for required inputs: +Con esta configuración, puedes definir inputs en tu componente que coincidan con las claves del resolver usando la función [`input`](api/core/input) e [`input.required`](api/core/input#required) para inputs requeridos: ```angular-ts import { Component, input } from '@angular/core'; @@ -125,21 +125,21 @@ export class UserDetail { } ``` -This approach provides better type safety and eliminates the need to inject `ActivatedRoute` just to access resolved data. +Este enfoque proporciona mejor seguridad de tipos y elimina la necesidad de inyectar `ActivatedRoute` solo para acceder a los datos resueltos. -## Error handling in resolvers +## Manejo de errores en resolvers -In the event of navigation failures, it is important to handle errors gracefully in your data resolvers. Otherwise, a `NavigationError` will occur and the navigation to the current route will fail which will lead to a poor experience for your users. +En caso de fallos de navegación, es importante manejar errores de forma elegante en tus data resolvers. De lo contrario, ocurrirá un `NavigationError` y la navegación a la ruta actual fallará, lo que conducirá a una mala experiencia para tus usuarios. -There are three primary ways to handle errors with data resolvers: +Hay tres formas principales de manejar errores con data resolvers: -1. [Centralizing error handling in `withNavigationErrorHandler`](#centralize-error-handling-in-withnavigationerrorhandler) -2. [Managing errors through a subscription to router events](#managing-errors-through-a-subscription-to-router-events) -3. [Handling errors directly in the resolver](#handling-errors-directly-in-the-resolver) +1. [Centralizar el manejo de errores en `withNavigationErrorHandler`](#centralize-error-handling-in-withnavigationerrorhandler) +2. [Gestionar errores a través de una suscripción a eventos del router](#managing-errors-through-a-subscription-to-router-events) +3. [Manejar errores directamente en el resolver](#handling-errors-directly-in-the-resolver) -### Centralize error handling in `withNavigationErrorHandler` +### Centralizar el manejo de errores en `withNavigationErrorHandler` -The [`withNavigationErrorHandler`](api/router/withNavigationErrorHandler) feature provides a centralized way to handle all navigation errors, including those from failed data resolvers. This approach keeps error handling logic in one place and prevents duplicate error handling code across resolvers. +La característica [`withNavigationErrorHandler`](api/router/withNavigationErrorHandler) proporciona una forma centralizada de manejar todos los errores de navegación, incluyendo los de data resolvers fallidos. Este enfoque mantiene la lógica de manejo de errores en un solo lugar y previene código duplicado de manejo de errores en los resolvers. ```ts import { bootstrapApplication } from '@angular/platform-browser'; @@ -163,20 +163,20 @@ bootstrapApplication(App, { }); ``` -With this configuration, your resolvers can focus on data fetching while letting the centralized handler manage error scenarios: +Con esta configuración, tus resolvers pueden enfocarse en la obtención de datos mientras dejan que el manejador centralizado gestione escenarios de error: ```ts export const userResolver: ResolveFn = (route) => { const userStore = inject(UserStore); const userId = route.paramMap.get('id')!; - // No need for explicit error handling - let it bubble up + // No es necesario manejo explícito de errores - dejar que burbujee return userStore.getUser(userId); }; ``` -### Managing errors through a subscription to router events +### Gestionar errores a través de una suscripción a eventos del router -You can also handle resolver errors by subscribing to router events and listening for [`NavigationError`](api/router/NavigationError) events. This approach gives you more granular control over error handling and allows you to implement custom error recovery logic. +También puedes manejar errores de resolver suscribiéndote a eventos del router y escuchando eventos [`NavigationError`](api/router/NavigationError). Este enfoque te da un control más granular sobre el manejo de errores y te permite implementar lógica personalizada de recuperación de errores. ```angular-ts import { Component, inject, signal } from '@angular/core'; @@ -226,15 +226,15 @@ export class App { } ``` -This approach is particularly useful when you need to: +Este enfoque es particularmente útil cuando necesitas: -- Implement custom retry logic for failed navigation -- Show specific error messages based on the type of failure -- Track navigation failures for analytics purposes +- Implementar lógica de reintento personalizada para navegación fallida +- Mostrar mensajes de error específicos basados en el tipo de fallo +- Rastrear fallos de navegación para propósitos de analytics -### Handling errors directly in the resolver +### Manejar errores directamente en el resolver -Here's an updated example of the `userResolver` that logs the error and navigates back to the generic `/users` page using the [`Router`](api/router/Router) service: +Aquí hay un ejemplo actualizado del `userResolver` que registra el error y navega de vuelta a la página genérica `/users` usando el servicio [`Router`](api/router/Router): ```ts import { inject } from '@angular/core'; @@ -257,13 +257,13 @@ export const userResolver: ResolveFn = (route) => { }; ``` -## Navigation loading considerations +## Consideraciones de carga de navegación -While data resolvers prevent loading states within components, they introduce a different UX consideration: navigation is blocked while resolvers execute. Users may experience delays between clicking a link and seeing the new route, especially with slow network requests. +Aunque los data resolvers previenen estados de carga dentro de los componentes, introducen una consideración UX diferente: la navegación se bloquea mientras los resolvers se ejecutan. Los usuarios pueden experimentar retrasos entre hacer clic en un enlace y ver la nueva ruta, especialmente con peticiones de red lentas. -### Providing navigation feedback +### Proporcionando retroalimentación de navegación -To improve user experience during resolver execution, you can listen to router events and show loading indicators: +Para mejorar la experiencia del usuario durante la ejecución de resolvers, puedes escuchar eventos del router y mostrar indicadores de carga: ```angular-ts import { Component, inject } from '@angular/core'; @@ -286,13 +286,13 @@ export class App { } ``` -This approach ensures users receive visual feedback that navigation is in progress while resolvers fetch data. +Este enfoque asegura que los usuarios reciban retroalimentación visual de que la navegación está en progreso mientras los resolvers obtienen datos. -## Best practices +## Mejores prácticas -- **Keep resolvers lightweight**: Resolvers should fetch essential data only and not everything the page could possibly need -- **Handle errors**: Always remember to handle errors gracefully to provide the best experience possible to users -- **Use caching**: Consider caching resolved data to improve performance -- **Consider navigation UX**: Implement loading indicators for resolver execution since navigation is blocked during data fetching -- **Set reasonable timeouts**: Avoid resolvers that could hang indefinitely and block navigation -- **Type safety**: Use TypeScript interfaces for resolved data +- **Mantén los resolvers ligeros**: Los resolvers deben obtener solo datos esenciales y no todo lo que la página podría necesitar posiblemente +- **Maneja errores**: Siempre recuerda manejar errores de forma elegante para proporcionar la mejor experiencia posible a los usuarios +- **Usa caché**: Considera cachear datos resueltos para mejorar el rendimiento +- **Considera la UX de navegación**: Implementa indicadores de carga para la ejecución de resolvers ya que la navegación se bloquea durante la obtención de datos +- **Establece timeouts razonables**: Evita resolvers que puedan colgarse indefinidamente y bloquear la navegación +- **Seguridad de tipos**: Usa interfaces de TypeScript para datos resueltos diff --git a/adev-es/src/content/guide/routing/define-routes.en.md b/adev-es/src/content/guide/routing/define-routes.en.md new file mode 100644 index 0000000..cfadb1a --- /dev/null +++ b/adev-es/src/content/guide/routing/define-routes.en.md @@ -0,0 +1,413 @@ +# Define routes + +Routes serve as the fundamental building blocks for navigation within an Angular app. + +## What are routes? + +In Angular, a **route** is an object that defines which component should render for a specific URL path or pattern, as well as additional configuration options about what happens when a user navigates to that URL. + +Here is a basic example of a route: + +```angular-ts +import { AdminPage } from './app-admin/app-admin.component'; + +const adminPage = { + path: 'admin', + component: AdminPage +} +``` + +For this route, when a user visits the `/admin` path, the app will display the `AdminPage` component. + +### Managing routes in your application + +Most projects define routes in a separate file that contains `routes` in the filename. + +A collection of routes looks like this: + +```angular-ts +import { Routes } from '@angular/router'; +import { HomePage } from './home-page/home-page.component'; +import { AdminPage } from './about-page/admin-page.component'; + +export const routes: Routes = [ + { + path: '', + component: HomePage, + }, + { + path: 'admin', + component: AdminPage, + }, +]; +``` + +Tip: If you generated a project with Angular CLI, your routes are defined in `src/app/app.routes.ts`. + +### Adding the router to your application + +When bootstrapping an Angular application without the Angular CLI, you can pass a configuration object that includes a `providers` array. + +Inside of the `providers` array, you can add the Angular router to your application by adding a `provideRouter` function call with your routes. + +```angular-ts +import { ApplicationConfig } from '@angular/core'; +import { provideRouter } from '@angular/router'; + +import { routes } from './app.routes'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideRouter(routes), + // ... + ] +}; +``` + +## Route URL Paths + +### Static URL Paths + +Static URL Paths refer to routes with predefined paths that don't change based on dynamic parameters. These are routes that match a `path` string exactly and have a fixed outcome. + +Examples of this include: + +- "/admin" +- "/blog" +- "/settings/account" + +### Define URL Paths with Route Parameters + +Parameterized URLs allow you to define dynamic paths that allow multiple URLs to the same component while dynamically displaying data based on parameters in the URL. + +You can define this type of pattern by adding parameters to your route's `path` string and prefixing each parameter with the colon (`:`) character. + +IMPORTANT: Parameters are distinct from information in the URL's [query string](https://en.wikipedia.org/wiki/Query_string). +Learn more about [query parameters in Angular in this guide](/guide/routing/read-route-state#query-parameters). + +The following example displays a user profile component based on the user id passed in through the URL. + +```angular-ts +import { Routes } from '@angular/router'; +import { UserProfile } from './user-profile/user-profile; + +const routes: Routes = [ + { path: 'user/:id', component: UserProfile } +]; +``` + +In this example, URLs such as `/user/leeroy` and `/user/jenkins` render the `UserProfile` component. This component can then read the `id` parameter and use it to perform additional work, such as fetching data. See [reading route state guide](/guide/routing/read-route-state) for details on reading route parameters. + +Valid route parameter names must start with a letter (a-z, A-Z) and can only contain: + +- Letters (a-z, A-Z) +- Numbers (0-9) +- Underscore (\_) +- Hyphen (-) + +You can also define paths with multiple parameters: + +```angular-ts +import { Routes } from '@angular/router'; +import { UserProfile } from './user-profile/user-profile.component'; +import { SocialMediaFeed } from './user-profile/social–media-feed.component'; + +const routes: Routes = [ + { path: 'user/:id/:social-media', component: SocialMediaFeed }, + { path: 'user/:id/', component: UserProfile }, +]; +``` + +With this new path, users can visit `/user/leeroy/youtube` and `/user/leeroy/bluesky` and see respective social media feeds based on the parameter for the user leeroy. + +See [Reading route state](/guide/routing/read-route-state) for details on reading route parameters. + +### Wildcards + +When you need to catch all routes for a specific path, the solution is a wildcard route which is defined with the double asterisk (`**`). + +A common example is defining a Page Not Found component. + +```angular-ts +import { Home } from './home/home.component'; +import { UserProfile } from './user-profile/user-profile.component'; +import { NotFound } from './not-found/not-found.component'; + +const routes: Routes = [ + { path: 'home', component: Home }, + { path: 'user/:id', component: UserProfile }, + { path: '**', component: NotFound } +]; +``` + +In this routes array, the app displays the `NotFound` component when the user visits any path outside of `home` and `user/:id`. + +Tip: Wildcard routes are typically placed at the end of a routes array. + +## How Angular matches URLs + +When you define routes, the order is important because Angular uses a first-match wins strategy. This means that once Angular matches a URL with a route `path`, it stops checking any further routes. As a result, always put more specific routes before less specific routes. + +The following example shows routes defined from most-specific to least specific: + +```angular-ts +const routes: Routes = [ + { path: '', component: HomeComponent }, // Empty path + { path: 'users/new', component: NewUserComponent }, // Static, most specific + { path: 'users/:id', component: UserDetailComponent }, // Dynamic + { path: 'users', component: UsersComponent }, // Static, less specific + { path: '**', component: NotFoundComponent } // Wildcard - always last +]; +``` + +If a user visits `/users/new`, Angular router would go through the following steps: + +1. Checks `''` - doesn't match +1. Checks `users/new` - matches! Stops here +1. Never reaches `users/:id` even though it could match +1. Never reaches `users` +1. Never reaches `**` + +## Loading Route Component Strategies + +Understanding how and when components load in Angular routing is crucial for building responsive web applications. Angular offers two primary strategies to control component loading behavior: + +1. **Eagerly loaded**: Components that are loaded immediately +2. **Lazily loaded**: Components loaded only when needed + +Each approach offers distinct advantages for different scenarios. + +### Eagerly loaded components + +When you define a route with the `component` property, the referenced component is eagerly loaded as part of the same JavaScript bundle as the route configuration. + +```angular-ts +import { Routes } from "@angular/router"; +import { HomePage } from "./components/home/home-page" +import { LoginPage } from "./components/auth/login-page" + +export const routes: Routes = [ + // HomePage and LoginPage are both directly referenced in this config, + // so their code is eagerly included in the same JavaScript bundle as this file. + { + path: "", + component: HomePage + }, + { + path: "login", + component: LoginPage + } +] +``` + +Eagerly loading route components like this means that the browser has to download and parse all of the JavaScript for these components as part of your initial page load, but the components are available to Angular immediately. + +While including more JavaScript in your initial page load leads to slower initial load times, this can lead to more seamless transitions as the user navigates through an application. + +### Lazily loaded components + +You can use the `loadComponent` property to lazily load the JavaScript for a route only at the point at which that route would become active. + +```angular-ts +import { Routes } from "@angular/router"; + +export const routes: Routes = [ + // The HomePage and LoginPage components are loaded lazily at the point at which + // their corresponding routes become active. + { + path: 'login', + loadComponent: () => import('./components/auth/login-page').then(m => m.LoginPage) + }, + { + path: '', + loadComponent: () => import('./components/home/home-page').then(m => m.HomePage) + } +] +``` + +The `loadComponent` property accepts a loader function that returns a Promise that resolves to an Angular component. In most cases, this function uses the standard [JavaScript dynamic import API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import). You can, however, use any arbitrary async loader function. + +Lazily loading routes can significantly improve the load speed of your Angular application by removing large portions of JavaScript from the initial bundle. These portions of your code compile into separate JavaScript "chunks" that the router requests only when the user visits the corresponding route. + +### Should I use an eager or a lazy route? + +There are many factors to consider when deciding on whether a route should be eager or lazy. + +In general, eager loading is recommended for primary landing page(s) while other pages would be lazy-loaded. + +Note: While lazy routes have the upfront performance benefit of reducing the amount of initial data requested by the user, it adds future data requests that could be undesirable. This is particularly true when dealing with nested lazy loading at multiple levels, which can significantly impact performance. + +## Redirects + +You can define a route that redirects to another route instead of rendering a component: + +```angular-ts +import { BlogComponent } from './home/blog.component'; + +const routes: Routes = [ + { + path: 'articles', + redirectTo: '/blog', + }, + { + path: 'blog', + component: BlogComponent + }, +]; +``` + +If you modify or remove a route, some users may still click on out-of-date links or bookmarks to that route. You can add a redirect to direct those users to an appropriate alternative route instead of a "not found" page. + +## Page titles + +You can associate a **title** with each route. Angular automatically updates the [page title](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title) when a route activates. Always define appropriate page titles for your application, as these titles are necessary to create an accessible experience. + +```ts +import { Routes } from '@angular/router'; +import { HomeComponent } from './home/home.component'; +import { AboutComponent } from './about/about.component'; +import { ProductsComponent } from './products/products.component'; + +const routes: Routes = [ + { + path: '', + component: HomeComponent, + title: 'Home Page' + }, + { + path: 'about', + component: AboutComponent, + title: 'About Us' + }, +]; +``` + +The page `title` property can be set dynamincally to a resolver function using [`ResolveFn`](/api/router/ResolveFn). + +```ts +const titleResolver: ResolveFn = (route) => route.queryParams['id']; +const routes: Routes = [ + ... + { + path: 'products', + component: ProductsComponent, + title: titleResolver, + } +]; + +``` + +Route titles can also be set via a service extending the [`TitleStrategy`](/api/router/TitleStrategy) abstract class. By default, Angular uses the [`DefaultTitleStrategy`](/api/router/DefaultTitleStrategy). + +## Route-level providers for dependency injection + +Each route has a `providers` property that lets you provide dependencies to that route's content via [dependency injection](/guide/di). + +Common scenarios where this can be helpful include applications that have different services based on whether the user is an admin or not. + +```angular-ts +export const ROUTES: Route[] = [ + { + path: 'admin', + providers: [ + AdminService, + {provide: ADMIN_API_KEY, useValue: '12345'}, + ], + children: [ + {path: 'users', component: AdminUsersComponent}, + {path: 'teams', component: AdminTeamsComponent}, + ], + }, + // ... other application routes that don't + // have access to ADMIN_API_KEY or AdminService. +]; +``` + +In this code sample, the `admin` path contains a protected data property of `ADMIN_API_KEY` that is only available to children within its section. As a result, no other paths will be able to access the data provided via `ADMIN_API_KEY`. + +See the [Dependency injection guide](/guide/di) for more information about providers and injection in Angular. + +## Associating data with routes + +Route data enables you to attach additional information to routes. You are able to configure how components behave based on this data. + +There are two ways to work with route data: static data that remains constant, and dynamic data that can change based on runtime conditions. + +### Static data + +You can associate arbitrary static data with a route via the `data` property in order to centralize things like route-specific metadata (e.g., analytics tracking, permissions, etc.): + +```angular-ts +import { Routes } from '@angular/router'; +import { HomeComponent } from './home/home.component'; +import { AboutComponent } from './about/about.component'; +import { ProductsComponent } from './products/products.component'; + +const routes: Routes = [ + { + path: 'about', + component: AboutComponent, + data: { analyticsId: '456' } + }, + { + path: '', + component: HomeComponent, + data: { analyticsId: '123' } + } +]; +``` + +In this code sample, the home and about page are configured with specific `analyticsId` which would then be used in their respective components for page tracking analytics. + +You can read this static data by injecting the `ActivatedRoute`. See [Reading route state](/guide/routing/read-route-state) for details. + +### Dynamic data with data resolvers + +When you need to provide dynamic data to a route, check out the [guide on route data resolvers](/guide/routing/data-resolvers). + +## Nested Routes + +Nested routes, also known as child routes, are a common technique for managing more complex navigation routes where a component has a sub-view that changes based on the URL. + +Diagram to illustrate nested routes + +You can add child routes to any route definition with the `children` property: + +```angular-ts +const routes: Routes = [ + { + path: 'product/:id', + component: ProductComponent, + children: [ + { + path: 'info', + component: ProductInfoComponent + }, + { + path: 'reviews', + component: ProductReviewsComponent + } + ] + } +] +``` + +The above example defines a route for a product page that allows a user to change whether the product info or reviews are displayed based on the url. + +The `children` property accepts an array of `Route` objects. + +To display child routes, the parent component (`ProductComponent` in the example above) includes its own ``. + +```angular-html + +
+

Product {{ id }}

+ +
+``` + +After adding child routes to the configuration and adding a `` to the component, navigation between URLs that match the child routes updates only the nested outlet. + +## Next steps + +Learn how to [display the contents of your routes with Outlets](/guide/routing/show-routes-with-outlets). diff --git a/adev-es/src/content/guide/routing/define-routes.md b/adev-es/src/content/guide/routing/define-routes.md index 3c7257b..380ff37 100644 --- a/adev-es/src/content/guide/routing/define-routes.md +++ b/adev-es/src/content/guide/routing/define-routes.md @@ -1,12 +1,12 @@ -# Define routes +# Definir rutas -Routes serve as the fundamental building blocks for navigation within an Angular app. +Las rutas sirven como los bloques de construcción fundamentales para la navegación dentro de una aplicación Angular. -## What are routes? +## ¿Qué son las rutas? -In Angular, a **route** is an object that defines which component should render for a specific URL path or pattern, as well as additional configuration options about what happens when a user navigates to that URL. +En Angular, una **ruta** es un objeto que define qué componente debe renderizar para una ruta URL específica o patrón, así como opciones de configuración adicionales sobre qué sucede cuando un usuario navega a esa URL. -Here is a basic example of a route: +Aquí hay un ejemplo básico de una ruta: ```angular-ts import { AdminPage } from './app-admin/app-admin.component'; @@ -17,13 +17,13 @@ const adminPage = { } ``` -For this route, when a user visits the `/admin` path, the app will display the `AdminPage` component. +Para esta ruta, cuando un usuario visita la ruta `/admin`, la aplicación mostrará el componente `AdminPage`. -### Managing routes in your application +### Gestionando rutas en tu aplicación -Most projects define routes in a separate file that contains `routes` in the filename. +La mayoría de los proyectos definen rutas en un archivo separado que contiene `routes` en el nombre del archivo. -A collection of routes looks like this: +Una colección de rutas se ve así: ```angular-ts import { Routes } from '@angular/router'; @@ -42,13 +42,13 @@ export const routes: Routes = [ ]; ``` -Tip: If you generated a project with Angular CLI, your routes are defined in `src/app/app.routes.ts`. +Consejo: Si generaste un proyecto con Angular CLI, tus rutas están definidas en `src/app/app.routes.ts`. -### Adding the router to your application +### Agregando el router a tu aplicación -When bootstrapping an Angular application without the Angular CLI, you can pass a configuration object that includes a `providers` array. +Al hacer bootstrap de una aplicación Angular sin Angular CLI, puedes pasar un objeto de configuración que incluye un array `providers`. -Inside of the `providers` array, you can add the Angular router to your application by adding a `provideRouter` function call with your routes. +Dentro del array `providers`, puedes agregar el router de Angular a tu aplicación agregando una llamada a la función `provideRouter` con tus rutas. ```angular-ts import { ApplicationConfig } from '@angular/core'; @@ -64,28 +64,28 @@ export const appConfig: ApplicationConfig = { }; ``` -## Route URL Paths +## Rutas URL -### Static URL Paths +### Rutas URL estáticas -Static URL Paths refer to routes with predefined paths that don't change based on dynamic parameters. These are routes that match a `path` string exactly and have a fixed outcome. +Las rutas URL estáticas se refieren a rutas con rutas predefinidas que no cambian según parámetros dinámicos. Estas son rutas que coinciden exactamente con un string `path` y tienen un resultado fijo. -Examples of this include: +Ejemplos de esto incluyen: - "/admin" - "/blog" - "/settings/account" -### Define URL Paths with Route Parameters +### Definir rutas URL con parámetros de ruta -Parameterized URLs allow you to define dynamic paths that allow multiple URLs to the same component while dynamically displaying data based on parameters in the URL. +Las URLs parametrizadas te permiten definir rutas dinámicas que permiten múltiples URLs al mismo componente mientras muestran datos dinámicamente según los parámetros en la URL. -You can define this type of pattern by adding parameters to your route’s `path` string and prefixing each parameter with the colon (`:`) character. +Puedes definir este tipo de patrón agregando parámetros al string `path` de tu ruta y prefijando cada parámetro con el carácter dos puntos (`:`). -IMPORTANT: Parameters are distinct from information in the URL's [query string](https://en.wikipedia.org/wiki/Query_string). -Learn more about [query parameters in Angular in this guide](/guide/routing/read-route-state#query-parameters). +IMPORTANTE: Los parámetros son distintos de la información en el [query string](https://en.wikipedia.org/wiki/Query_string) de la URL. +Aprende más sobre [parámetros de consulta en Angular en esta guía](/guide/routing/read-route-state#query-parameters). -The following example displays a user profile component based on the user id passed in through the URL. +El siguiente ejemplo muestra un componente de perfil de usuario basado en el id de usuario pasado a través de la URL. ```angular-ts import { Routes } from '@angular/router'; @@ -96,16 +96,16 @@ const routes: Routes = [ ]; ``` -In this example, URLs such as `/user/leeroy` and `/user/jenkins` render the `UserProfile` component. This component can then read the `id` parameter and use it to perform additional work, such as fetching data. See [reading route state guide](/guide/routing/read-route-state) for details on reading route parameters. +En este ejemplo, URLs como `/user/leeroy` y `/user/jenkins` renderizan el componente `UserProfile`. Este componente puede entonces leer el parámetro `id` y usarlo para realizar trabajo adicional, como obtener datos. Consulta la [guía de lectura de estado de ruta](/guide/routing/read-route-state) para detalles sobre la lectura de parámetros de ruta. -Valid route parameter names must start with a letter (a-z, A-Z) and can only contain: +Los nombres de parámetros de ruta válidos deben comenzar con una letra (a-z, A-Z) y solo pueden contener: -- Letters (a-z, A-Z) -- Numbers (0-9) -- Underscore (\_) -- Hyphen (-) +- Letras (a-z, A-Z) +- Números (0-9) +- Guión bajo (\_) +- Guión (-) -You can also define paths with multiple parameters: +También puedes definir rutas con múltiples parámetros: ```angular-ts import { Routes } from '@angular/router'; @@ -118,15 +118,15 @@ const routes: Routes = [ ]; ``` -With this new path, users can visit `/user/leeroy/youtube` and `/user/leeroy/bluesky` and see respective social media feeds based on the parameter for the user leeroy. +Con esta nueva ruta, los usuarios pueden visitar `/user/leeroy/youtube` y `/user/leeroy/bluesky` y ver feeds de redes sociales respectivos basados en el parámetro para el usuario leeroy. -See [Reading route state](/guide/routing/read-route-state) for details on reading route parameters. +Consulta [Leer estado de ruta](/guide/routing/read-route-state) para detalles sobre la lectura de parámetros de ruta. -### Wildcards +### Comodines -When you need to catch all routes for a specific path, the solution is a wildcard route which is defined with the double asterisk (`**`). +Cuando necesitas capturar todas las rutas para una ruta específica, la solución es una ruta comodín que se define con el doble asterisco (`**`). -A common example is defining a Page Not Found component. +Un ejemplo común es definir un componente de Página No Encontrada. ```angular-ts import { Home } from './home/home.component'; @@ -140,46 +140,46 @@ const routes: Routes = [ ]; ``` -In this routes array, the app displays the `NotFound` component when the user visits any path outside of `home` and `user/:id`. +En este array de rutas, la aplicación muestra el componente `NotFound` cuando el usuario visita cualquier ruta fuera de `home` y `user/:id`. -Tip: Wildcard routes are typically placed at the end of a routes array. +Consejo: Las rutas comodín típicamente se colocan al final de un array de rutas. -## How Angular matches URLs +## Cómo Angular hace coincidir URLs -When you define routes, the order is important because Angular uses a first-match wins strategy. This means that once Angular matches a URL with a route `path`, it stops checking any further routes. As a result, always put more specific routes before less specific routes. +Cuando defines rutas, el orden es importante porque Angular usa una estrategia de primera coincidencia gana. Esto significa que una vez que Angular hace coincidir una URL con un `path` de ruta, deja de verificar más rutas. Como resultado, siempre coloca rutas más específicas antes que rutas menos específicas. -The following example shows routes defined from most-specific to least specific: +El siguiente ejemplo muestra rutas definidas de más específica a menos específica: ```angular-ts const routes: Routes = [ - { path: '', component: HomeComponent }, // Empty path - { path: 'users/new', component: NewUserComponent }, // Static, most specific - { path: 'users/:id', component: UserDetailComponent }, // Dynamic - { path: 'users', component: UsersComponent }, // Static, less specific - { path: '**', component: NotFoundComponent } // Wildcard - always last + { path: '', component: HomeComponent }, // Ruta vacía + { path: 'users/new', component: NewUserComponent }, // Estática, más específica + { path: 'users/:id', component: UserDetailComponent }, // Dinámica + { path: 'users', component: UsersComponent }, // Estática, menos específica + { path: '**', component: NotFoundComponent } // Comodín - siempre último ]; ``` -If a user visits `/users/new`, Angular router would go through the following steps: +Si un usuario visita `/users/new`, el router de Angular pasaría por los siguientes pasos: -1. Checks `''` - doesn't match -1. Checks `users/new` - matches! Stops here -1. Never reaches `users/:id` even though it could match -1. Never reaches `users` -1. Never reaches `**` +1. Verifica `''` - no coincide +1. Verifica `users/new` - ¡coincide! Se detiene aquí +1. Nunca alcanza `users/:id` aunque podría coincidir +1. Nunca alcanza `users` +1. Nunca alcanza `**` -## Loading Route Component Strategies +## Estrategias de carga de componentes de ruta -Understanding how and when components load in Angular routing is crucial for building responsive web applications. Angular offers two primary strategies to control component loading behavior: +Entender cómo y cuándo se cargan los componentes en el enrutamiento en Angular es crucial para construir aplicaciones web responsivas. Angular ofrece dos estrategias principales para controlar el comportamiento de carga de componentes: -1. **Eagerly loaded**: Components that are loaded immediately -2. **Lazily loaded**: Components loaded only when needed +1. **Carga eager (inmediata)**: Componentes que se cargan inmediatamente +2. **Carga lazy (diferida)**: Componentes cargados solo cuando son necesarios -Each approach offers distinct advantages for different scenarios. +Cada enfoque ofrece ventajas distintas para diferentes escenarios. -### Eagerly loaded components +### Componentes cargados de forma eager -When you define a route with the `component` property, the referenced component is eagerly loaded as part of the same JavaScript bundle as the route configuration. +Cuando defines una ruta con la propiedad `component`, el componente referenciado se carga de forma eager como parte del mismo bundle de JavaScript que la configuración de ruta. ```angular-ts import { Routes } from "@angular/router"; @@ -187,8 +187,8 @@ import { HomePage } from "./components/home/home-page" import { LoginPage } from "./components/auth/login-page" export const routes: Routes = [ - // HomePage and LoginPage are both directly referenced in this config, - // so their code is eagerly included in the same JavaScript bundle as this file. + // HomePage y LoginPage están ambos referenciados directamente en esta configuración, + // por lo que su código se incluye de forma eager en el mismo bundle de JavaScript que este archivo. { path: "", component: HomePage @@ -200,20 +200,20 @@ export const routes: Routes = [ ] ``` -Eagerly loading route components like this means that the browser has to download and parse all of the JavaScript for these components as part of your initial page load, but the components are available to Angular immediately. +Cargar componentes de ruta de forma eager de esta manera significa que el navegador tiene que descargar y parsear todo el JavaScript para estos componentes como parte de la carga inicial de tu página, pero los componentes están disponibles para Angular inmediatamente. -While including more JavaScript in your initial page load leads to slower initial load times, this can lead to more seamless transitions as the user navigates through an application. +Aunque incluir más JavaScript en la carga inicial de tu página conduce a tiempos de carga inicial más lentos, esto puede conducir a transiciones más fluidas a medida que el usuario navega por una aplicación. -### Lazily loaded components +### Componentes cargados de forma lazy -You can use the `loadComponent` property to lazily load the JavaScript for a route only at the point at which that route would become active. +Puedes usar la propiedad `loadComponent` para cargar de forma lazy el JavaScript para una ruta solo en el punto en que esa ruta se vuelva activa. ```angular-ts import { Routes } from "@angular/router"; export const routes: Routes = [ - // The HomePage and LoginPage components are loaded lazily at the point at which - // their corresponding routes become active. + // Los componentes HomePage y LoginPage se cargan de forma lazy en el punto en que + // sus rutas correspondientes se vuelven activas. { path: 'login', loadComponent: () => import('./components/auth/login-page').then(m => m.LoginPage) @@ -225,21 +225,21 @@ export const routes: Routes = [ ] ``` -The `loadComponent` property accepts a loader function that returns a Promise that resolves to an Angular component. In most cases, this function uses the standard [JavaScript dynamic import API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import). You can, however, use any arbitrary async loader function. +La propiedad `loadComponent` acepta una función loader que retorna una Promise que se resuelve a un componente de Angular. En la mayoría de los casos, esta función usa la [API de importación dinámica estándar de JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import). Sin embargo, puedes usar cualquier función loader asíncrona arbitraria. -Lazily loading routes can significantly improve the load speed of your Angular application by removing large portions of JavaScript from the initial bundle. These portions of your code compile into separate JavaScript "chunks" that the router requests only when the user visits the corresponding route. +Cargar rutas de forma lazy puede mejorar significativamente la velocidad de carga de tu aplicación Angular al eliminar grandes porciones de JavaScript del bundle inicial. Estas porciones de tu código se compilan en "chunks" de JavaScript separados que el router solicita solo cuando el usuario visita la ruta correspondiente. -### Should I use an eager or a lazy route? +### ¿Debo usar una ruta eager o lazy? -There are many factors to consider when deciding on whether a route should be eager or lazy. +Hay muchos factores a considerar al decidir si una ruta debe ser eager o lazy. -In general, eager loading is recommended for primary landing page(s) while other pages would be lazy-loaded. +En general, se recomienda la carga eager para la(s) página(s) de destino principal(es) mientras que otras páginas se cargarían de forma lazy. -Note: While lazy routes have the upfront performance benefit of reducing the amount of initial data requested by the user, it adds future data requests that could be undesirable. This is particularly true when dealing with nested lazy loading at multiple levels, which can significantly impact performance. +Nota: Si bien las rutas lazy tienen el beneficio de rendimiento inicial de reducir la cantidad de datos iniciales solicitados por el usuario, agrega futuras peticiones de datos que podrían ser indeseables. Esto es particularmente cierto cuando se trata de carga lazy anidada en múltiples niveles, lo que puede impactar significativamente el rendimiento. -## Redirects +## Redirecciones -You can define a route that redirects to another route instead of rendering a component: +Puedes definir una ruta que redirige a otra ruta en lugar de renderizar un componente: ```angular-ts import { BlogComponent } from './home/blog.component'; @@ -256,11 +256,11 @@ const routes: Routes = [ ]; ``` -If you modify or remove a route, some users may still click on out-of-date links or bookmarks to that route. You can add a redirect to direct those users to an appropriate alternative route instead of a "not found" page. +Si modificas o eliminas una ruta, algunos usuarios aún pueden hacer clic en enlaces desactualizados o marcadores a esa ruta. Puedes agregar una redirección para dirigir a esos usuarios a una ruta alternativa apropiada en lugar de una página "no encontrada". -## Page titles +## Títulos de página -You can associate a **title** with each route. Angular automatically updates the [page title](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title) when a route activates. Always define appropriate page titles for your application, as these titles are necessary to create an accessible experience. +Puedes asociar un **título** con cada ruta. Angular actualiza automáticamente el [título de página](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title) cuando una ruta se activa. Siempre define títulos de página apropiados para tu aplicación, ya que estos títulos son necesarios para crear una experiencia accesible. ```ts import { Routes } from '@angular/router'; @@ -282,7 +282,7 @@ const routes: Routes = [ ]; ``` -The page `title` property can be set dynamincally to a resolver function using [`ResolveFn`](/api/router/ResolveFn). +La propiedad `title` de la página puede establecerse dinámicamente a una función resolver usando [`ResolveFn`](/api/router/ResolveFn). ```ts const titleResolver: ResolveFn = (route) => route.queryParams['id']; @@ -297,13 +297,13 @@ const routes: Routes = [ ``` -Route titles can also be set via a service extending the [`TitleStrategy`](/api/router/TitleStrategy) abstract class. By default, Angular uses the [`DefaultTitleStrategy`](/api/router/DefaultTitleStrategy). +Los títulos de ruta también se pueden establecer a través de un servicio que extiende la clase abstracta [`TitleStrategy`](/api/router/TitleStrategy). Por defecto, Angular usa el [`DefaultTitleStrategy`](/api/router/DefaultTitleStrategy). -## Route-level providers for dependency injection +## Proveedores a nivel de ruta para inyección de dependencias -Each route has a `providers` property that lets you provide dependencies to that route's content via [dependency injection](/guide/di). +Cada ruta tiene una propiedad `providers` que te permite proporcionar dependencias al contenido de esa ruta a través de [inyección de dependencias](/guide/di). -Common scenarios where this can be helpful include applications that have different services based on whether the user is an admin or not. +Escenarios comunes donde esto puede ser útil incluyen aplicaciones que tienen diferentes servicios según si el usuario es admin o no. ```angular-ts export const ROUTES: Route[] = [ @@ -318,24 +318,24 @@ export const ROUTES: Route[] = [ {path: 'teams', component: AdminTeamsComponent}, ], }, - // ... other application routes that don't - // have access to ADMIN_API_KEY or AdminService. + // ... otras rutas de aplicación que no + // tienen acceso a ADMIN_API_KEY o AdminService. ]; ``` -In this code sample, the `admin` path contains a protected data property of `ADMIN_API_KEY` that is only available to children within its section. As a result, no other paths will be able to access the data provided via `ADMIN_API_KEY`. +En este ejemplo de código, la ruta `admin` contiene una propiedad de datos protegida de `ADMIN_API_KEY` que solo está disponible para los hijos dentro de su sección. Como resultado, ninguna otra ruta podrá acceder a los datos proporcionados a través de `ADMIN_API_KEY`. -See the [Dependency injection guide](/guide/di) for more information about providers and injection in Angular. +Consulta la [guía de Inyección de dependencias](/guide/di) para más información sobre proveedores e inyección en Angular. -## Associating data with routes +## Asociando datos con rutas -Route data enables you to attach additional information to routes. You are able to configure how components behave based on this data. +Los datos de ruta te permiten adjuntar información adicional a las rutas. Puedes configurar cómo se comportan los componentes según estos datos. -There are two ways to work with route data: static data that remains constant, and dynamic data that can change based on runtime conditions. +Hay dos formas de trabajar con datos de ruta: datos estáticos que permanecen constantes, y datos dinámicos que pueden cambiar según condiciones de tiempo de ejecución. -### Static data +### Datos estáticos -You can associate arbitrary static data with a route via the `data` property in order to centralize things like route-specific metadata (e.g., analytics tracking, permissions, etc.): +Puedes asociar datos estáticos arbitrarios con una ruta a través de la propiedad `data` para centralizar cosas como metadatos específicos de ruta (por ejemplo, seguimiento de analytics, permisos, etc.): ```angular-ts import { Routes } from '@angular/router'; @@ -357,21 +357,21 @@ const routes: Routes = [ ]; ``` -In this code sample, the home and about page are configured with specific `analyticsId` which would then be used in their respective components for page tracking analytics. +En este ejemplo de código, la página de inicio y la página about están configuradas con un `analyticsId` específico que luego se usaría en sus respectivos componentes para el seguimiento de analytics de página. -You can read this static data by injecting the `ActivatedRoute`. See [Reading route state](/guide/routing/read-route-state) for details. +Puedes leer estos datos estáticos inyectando el `ActivatedRoute`. Consulta [Leer estado de ruta](/guide/routing/read-route-state) para más detalles. -### Dynamic data with data resolvers +### Datos dinámicos con data resolvers -When you need to provide dynamic data to a route, check out the [guide on route data resolvers](/guide/routing/data-resolvers). +Cuando necesitas proporcionar datos dinámicos a una ruta, consulta la [guía sobre resolvers de datos de ruta](/guide/routing/data-resolvers). -## Nested Routes +## Rutas anidadas -Nested routes, also known as child routes, are a common technique for managing more complex navigation routes where a component has a sub-view that changes based on the URL. +Las rutas anidadas, también conocidas como rutas hijas, son una técnica común para gestionar rutas de navegación más complejas donde un componente tiene una sub-vista que cambia según la URL. -Diagram to illustrate nested routes +Diagrama para ilustrar rutas anidadas -You can add child routes to any route definition with the `children` property: +Puedes agregar rutas hijas a cualquier definición de ruta con la propiedad `children`: ```angular-ts const routes: Routes = [ @@ -392,11 +392,11 @@ const routes: Routes = [ ] ``` -The above example defines a route for a product page that allows a user to change whether the product info or reviews are displayed based on the url. +El ejemplo anterior define una ruta para una página de producto que permite a un usuario cambiar si se muestra la información del producto o las reseñas según la url. -The `children` property accepts an array of `Route` objects. +La propiedad `children` acepta un array de objetos `Route`. -To display child routes, the parent component (`ProductComponent` in the example above) includes its own ``. +Para mostrar rutas hijas, el componente padre (`ProductComponent` en el ejemplo anterior) incluye su propio ``. ```angular-html @@ -406,8 +406,8 @@ To display child routes, the parent component (`ProductComponent` in the example ``` -After adding child routes to the configuration and adding a `` to the component, navigation between URLs that match the child routes updates only the nested outlet. +Después de agregar rutas hijas a la configuración y agregar un `` al componente, la navegación entre URLs que coinciden con las rutas hijas actualiza solo el outlet anidado. -## Next steps +## Próximos pasos -Learn how to [display the contents of your routes with Outlets](/guide/routing/show-routes-with-outlets). +Aprende cómo [mostrar el contenido de tus rutas con Outlets](/guide/routing/show-routes-with-outlets). diff --git a/adev-es/src/content/guide/routing/lifecycle-and-events.en.md b/adev-es/src/content/guide/routing/lifecycle-and-events.en.md new file mode 100644 index 0000000..6e3676f --- /dev/null +++ b/adev-es/src/content/guide/routing/lifecycle-and-events.en.md @@ -0,0 +1,243 @@ +# Router Lifecycle and Events + +Angular Router provides a comprehensive set of lifecycle hooks and events that allow you to respond to navigation changes and execute custom logic during the routing process. + +## Common router events + +The Angular Router emits navigation events that you can subscribe to in order to track the navigation lifecycle. These events are available through the `Router.events` observable. This section covers common routing lifecycle events for navigation and error tracking (in chronological order). + +| Events | Description | +| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | +| [`NavigationStart`](api/router/NavigationStart) | Occurs when navigation begins and contains the requested URL. | +| [`RoutesRecognized`](api/router/RoutesRecognized) | Occurs after the router determines which route matches the URL and contains the route state information. | +| [`GuardsCheckStart`](api/router/GuardsCheckStart) | Begins the route guard phase. The router evaluates route guards like `canActivate` and `canDeactivate`. | +| [`GuardsCheckEnd`](api/router/GuardsCheckEnd) | Signals completion of guard evaluation. Contains the result (allowed/denied). | +| [`ResolveStart`](api/router/ResolveStart) | Begins the data resolution phase. Route resolvers start fetching data. | +| [`ResolveEnd`](api/router/ResolveEnd) | Data resolution completes. All required data becomes available. | +| [`NavigationEnd`](api/router/NavigationEnd) | Final event when navigation completes successfully. The router updates the URL. | +| [`NavigationSkipped`](api/router/NavigationSkipped) | Occurs when the router skips navigation (e.g., same URL navigation). | + +The following are common error events: + +| Event | Description | +| ------------------------------------------------- | -------------------------------------------------------------------------------- | +| [`NavigationCancel`](api/router/NavigationCancel) | Occurs when the router cancels navigation. Often due to a guard returning false. | +| [`NavigationError`](api/router/NavigationError) | Occurs when navigation fails. Could be due to invalid routes or resolver errors. | + +For a list of all lifecycle events, check out the [complete table of this guide](#all-router-events). + +## How to subscribe to router events + +When you want to run code during specific navigation lifecycle events, you can do so by subscribing to the `router.events` and checking the instance of the event: + +```ts +// Example of subscribing to router events +import { Component, inject, signal, effect } from '@angular/core'; +import { Event, Router, NavigationStart, NavigationEnd } from '@angular/router'; + +@Component({ ... }) +export class RouterEventsComponent { + private readonly router = inject(Router); + + constructor() { + // Subscribe to router events and react to events + this.router.events.pipe(takeUntilDestroyed()).subscribe((event: Event) => { + if (event instanceof NavigationStart) { + // Navigation starting + console.log('Navigation starting:', event.url); + } + if (event instanceof NavigationEnd) { + // Navigation completed + console.log('Navigation completed:', event.url); + } + }); + } +} +``` + +Note: The [`Event`](api/router/Event) type from `@angular/router` is named the same as the regular global [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event) type, but it is different from the [`RouterEvent`](api/router/RouterEvent) type. + +## How to debug routing events + +Debugging router navigation issues can be challenging without visibility into the event sequence. Angular provides a built-in debugging feature that logs all router events to the console, helping you understand the navigation flow and identify where issues occur. + +When you need to inspect a Router event sequence, you can enable logging for internal navigation events for debugging. You can configure this by passing a configuration option (`withDebugTracing()`) that enables detailed console logging of all routing events. + +```ts +import { provideRouter, withDebugTracing } from '@angular/router'; + +const appRoutes: Routes = []; +bootstrapApplication(AppComponent, + { + providers: [ + provideRouter(appRoutes, withDebugTracing()) + ] + } +); +``` + +For more information, check out the official docs on [`withDebugTracing`](api/router/withDebugTracing). + +## Common use cases + +Router events enable many practical features in real-world applications. Here are some common patterns that are used with router events. + +### Loading indicators + +Show loading indicators during navigation: + +```angular-ts +import { Component, inject } from '@angular/core'; +import { Router } from '@angular/router'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { map } from 'rxjs/operators'; + +@Component({ + selector: 'app-loading', + template: ` + @if (loading()) { +
Loading...
+ } + ` +}) +export class AppComponent { + private router = inject(Router); + + readonly loading = toSignal( + this.router.events.pipe( + map(() => !!this.router.getCurrentNavigation()) + ), + { initialValue: false } + ); +} +``` + +### Analytics tracking + +Track page views for analytics: + +```typescript +import { Component, inject, signal, effect } from '@angular/core'; +import { Router, NavigationEnd } from '@angular/router'; + +@Injectable({ providedIn: 'root' }) +export class AnalyticsService { + private router = inject(Router); + private destroyRef = inject(DestroyRef); + + startTracking() { + this.router.events.pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe(event => { + // Track page views when URL changes + if (event instanceof NavigationEnd) { + // Send page view to analytics + this.analytics.trackPageView(url); + } + }); + } + + private analytics = { + trackPageView: (url: string) => { + console.log('Page view tracked:', url); + } + }; +} +``` + +### Error handling + +Handle navigation errors gracefully and provide user feedback: + +```angular-ts +import { Component, inject, signal } from '@angular/core'; +import { Router, NavigationStart, NavigationError, NavigationCancel, NavigationCancellationCode } from '@angular/router'; + +@Component({ + selector: 'app-error-handler', + template: ` + @if (errorMessage()) { +
+ {{ errorMessage() }} + +
+ } + ` +}) +export class ErrorHandlerComponent { + private router = inject(Router); + readonly errorMessage = signal(''); + + constructor() { + this.router.events.pipe(takeUntilDestroyed()).subscribe(event => { + if (event instanceof NavigationStart) { + this.errorMessage.set(''); + } else if (event instanceof NavigationError) { + console.error('Navigation error:', event.error); + this.errorMessage.set('Failed to load page. Please try again.'); + } else if (event instanceof NavigationCancel) { + console.warn('Navigation cancelled:', event.reason); + if (event.reason === NavigationCancellationCode.GuardRejected) { + this.errorMessage.set('Access denied. Please check your permissions.'); + } + } + }); + } + + dismissError() { + this.errorMessage.set(''); + } +} +``` + +## All router events + +For reference, here is the complete list of all router events available in Angular. These events are organized by category and listed in the order they typically occur during navigation. + +### Navigation events + +These events track the core navigation process from start through route recognition, guard checks, and data resolution. They provide visibility into each phase of the navigation lifecycle. + +| Event | Description | +| --------------------------------------------------------- | --------------------------------------------------------------- | +| [`NavigationStart`](api/router/NavigationStart) | Occurs when navigation starts | +| [`RouteConfigLoadStart`](api/router/RouteConfigLoadStart) | Occurs before lazy loading a route configuration | +| [`RouteConfigLoadEnd`](api/router/RouteConfigLoadEnd) | Occurs after a lazy-loaded route configuration loads | +| [`RoutesRecognized`](api/router/RoutesRecognized) | Occurs when the router parses the URL and recognizes the routes | +| [`GuardsCheckStart`](api/router/GuardsCheckStart) | Occurs at the start of the guard phase | +| [`GuardsCheckEnd`](api/router/GuardsCheckEnd) | Occurs at the end of the guard phase | +| [`ResolveStart`](api/router/ResolveStart) | Occurs at the start of the resolve phase | +| [`ResolveEnd`](api/router/ResolveEnd) | Occurs at the end of the resolve phase | + +### Activation events + +These events occur during the activation phase when route components are being instantiated and initialized. Activation events fire for each route in the route tree, including parent and child routes. + +| Event | Description | +| --------------------------------------------------------- | --------------------------------------------- | +| [`ActivationStart`](api/router/ActivationStart) | Occurs at the start of route activation | +| [`ChildActivationStart`](api/router/ChildActivationStart) | Occurs at the start of child route activation | +| [`ActivationEnd`](api/router/ActivationEnd) | Occurs at the end of route activation | +| [`ChildActivationEnd`](api/router/ChildActivationEnd) | Occurs at the end of child route activation | + +### Navigation completion events + +These events represent the final outcome of a navigation attempt. Every navigation will end with exactly one of these events, indicating whether it succeeded, was cancelled, failed, or was skipped. + +| Event | Description | +| --------------------------------------------------- | ------------------------------------------------------------------- | +| [`NavigationEnd`](api/router/NavigationEnd) | Occurs when navigation ends successfully | +| [`NavigationCancel`](api/router/NavigationCancel) | Occurs when the router cancels navigation | +| [`NavigationError`](api/router/NavigationError) | Occurs when navigation fails due to an unexpected error | +| [`NavigationSkipped`](api/router/NavigationSkipped) | Occurs when the router skips navigation (e.g., same URL navigation) | + +### Other events + +There is one additional event that occurs outside the main navigation lifecycle, but it is still part of the router's event system. + +| Event | Description | +| ----------------------------- | ----------------------- | +| [`Scroll`](api/router/Scroll) | Occurs during scrolling | + +## Next steps + +Learn more about [route guards](/guide/routing/route-guards) and [common router tasks](/guide/routing/common-router-tasks). diff --git a/adev-es/src/content/guide/routing/lifecycle-and-events.md b/adev-es/src/content/guide/routing/lifecycle-and-events.md index 6e3676f..31eb92c 100644 --- a/adev-es/src/content/guide/routing/lifecycle-and-events.md +++ b/adev-es/src/content/guide/routing/lifecycle-and-events.md @@ -1,37 +1,37 @@ -# Router Lifecycle and Events +# Ciclo de vida y eventos del Router -Angular Router provides a comprehensive set of lifecycle hooks and events that allow you to respond to navigation changes and execute custom logic during the routing process. +Angular Router proporciona un conjunto completo de hooks de ciclo de vida y eventos que te permiten responder a cambios de navegación y ejecutar lógica personalizada durante el proceso de enrutamiento. -## Common router events +## Eventos comunes del router -The Angular Router emits navigation events that you can subscribe to in order to track the navigation lifecycle. These events are available through the `Router.events` observable. This section covers common routing lifecycle events for navigation and error tracking (in chronological order). +Angular Router emite eventos de navegación a los que puedes suscribirte para rastrear el ciclo de vida de la navegación. Estos eventos están disponibles a través del observable `Router.events`. Esta sección cubre eventos comunes del ciclo de vida de enrutamiento para navegación y seguimiento de errores (en orden cronológico). -| Events | Description | +| Eventos | Descripción | | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -| [`NavigationStart`](api/router/NavigationStart) | Occurs when navigation begins and contains the requested URL. | -| [`RoutesRecognized`](api/router/RoutesRecognized) | Occurs after the router determines which route matches the URL and contains the route state information. | -| [`GuardsCheckStart`](api/router/GuardsCheckStart) | Begins the route guard phase. The router evaluates route guards like `canActivate` and `canDeactivate`. | -| [`GuardsCheckEnd`](api/router/GuardsCheckEnd) | Signals completion of guard evaluation. Contains the result (allowed/denied). | -| [`ResolveStart`](api/router/ResolveStart) | Begins the data resolution phase. Route resolvers start fetching data. | -| [`ResolveEnd`](api/router/ResolveEnd) | Data resolution completes. All required data becomes available. | -| [`NavigationEnd`](api/router/NavigationEnd) | Final event when navigation completes successfully. The router updates the URL. | -| [`NavigationSkipped`](api/router/NavigationSkipped) | Occurs when the router skips navigation (e.g., same URL navigation). | - -The following are common error events: - -| Event | Description | +| [`NavigationStart`](api/router/NavigationStart) | Ocurre cuando comienza la navegación y contiene la URL solicitada. | +| [`RoutesRecognized`](api/router/RoutesRecognized) | Ocurre después de que el router determina qué ruta coincide con la URL y contiene la información del estado de la ruta. | +| [`GuardsCheckStart`](api/router/GuardsCheckStart) | Comienza la fase de guards de ruta. El router evalúa guards de ruta como `canActivate` y `canDeactivate`. | +| [`GuardsCheckEnd`](api/router/GuardsCheckEnd) | Señala la finalización de la evaluación de guards. Contiene el resultado (permitido/denegado). | +| [`ResolveStart`](api/router/ResolveStart) | Comienza la fase de resolución de datos. Los resolvers de ruta comienzan a obtener datos. | +| [`ResolveEnd`](api/router/ResolveEnd) | La resolución de datos se completa. Todos los datos requeridos están disponibles. | +| [`NavigationEnd`](api/router/NavigationEnd) | Evento final cuando la navegación se completa exitosamente. El router actualiza la URL. | +| [`NavigationSkipped`](api/router/NavigationSkipped) | Ocurre cuando el router omite la navegación (por ejemplo, navegación a la misma URL). | + +Los siguientes son eventos de error comunes: + +| Evento | Descripción | | ------------------------------------------------- | -------------------------------------------------------------------------------- | -| [`NavigationCancel`](api/router/NavigationCancel) | Occurs when the router cancels navigation. Often due to a guard returning false. | -| [`NavigationError`](api/router/NavigationError) | Occurs when navigation fails. Could be due to invalid routes or resolver errors. | +| [`NavigationCancel`](api/router/NavigationCancel) | Ocurre cuando el router cancela la navegación. A menudo debido a que un guard retorna false. | +| [`NavigationError`](api/router/NavigationError) | Ocurre cuando la navegación falla. Podría ser debido a rutas inválidas o errores de resolver. | -For a list of all lifecycle events, check out the [complete table of this guide](#all-router-events). +Para una lista de todos los eventos de ciclo de vida, consulta la [tabla completa de esta guía](#all-router-events). -## How to subscribe to router events +## Cómo suscribirse a eventos del router -When you want to run code during specific navigation lifecycle events, you can do so by subscribing to the `router.events` and checking the instance of the event: +Cuando quieres ejecutar código durante eventos específicos del ciclo de vida de navegación, puedes hacerlo suscribiéndote a `router.events` y verificando la instancia del evento: ```ts -// Example of subscribing to router events +// Ejemplo de suscripción a eventos del router import { Component, inject, signal, effect } from '@angular/core'; import { Event, Router, NavigationStart, NavigationEnd } from '@angular/router'; @@ -40,14 +40,14 @@ export class RouterEventsComponent { private readonly router = inject(Router); constructor() { - // Subscribe to router events and react to events + // Suscribirse a eventos del router y reaccionar a eventos this.router.events.pipe(takeUntilDestroyed()).subscribe((event: Event) => { if (event instanceof NavigationStart) { - // Navigation starting + // Navegación iniciando console.log('Navigation starting:', event.url); } if (event instanceof NavigationEnd) { - // Navigation completed + // Navegación completada console.log('Navigation completed:', event.url); } }); @@ -55,13 +55,13 @@ export class RouterEventsComponent { } ``` -Note: The [`Event`](api/router/Event) type from `@angular/router` is named the same as the regular global [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event) type, but it is different from the [`RouterEvent`](api/router/RouterEvent) type. +Nota: El tipo [`Event`](api/router/Event) de `@angular/router` tiene el mismo nombre que el tipo global regular [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event), pero es diferente del tipo [`RouterEvent`](api/router/RouterEvent). -## How to debug routing events +## Cómo depurar eventos de enrutamiento -Debugging router navigation issues can be challenging without visibility into the event sequence. Angular provides a built-in debugging feature that logs all router events to the console, helping you understand the navigation flow and identify where issues occur. +Depurar problemas de navegación del router puede ser desafiante sin visibilidad en la secuencia de eventos. Angular proporciona una característica de depuración integrada que registra todos los eventos del router en la consola, ayudándote a entender el flujo de navegación e identificar dónde ocurren los problemas. -When you need to inspect a Router event sequence, you can enable logging for internal navigation events for debugging. You can configure this by passing a configuration option (`withDebugTracing()`) that enables detailed console logging of all routing events. +Cuando necesitas inspeccionar una secuencia de eventos del Router, puedes habilitar el registro para eventos de navegación internos para depuración. Puedes configurar esto pasando una opción de configuración (`withDebugTracing()`) que habilita el registro detallado en consola de todos los eventos de enrutamiento. ```ts import { provideRouter, withDebugTracing } from '@angular/router'; @@ -76,15 +76,15 @@ bootstrapApplication(AppComponent, ); ``` -For more information, check out the official docs on [`withDebugTracing`](api/router/withDebugTracing). +Para más información, consulta la documentación oficial sobre [`withDebugTracing`](api/router/withDebugTracing). -## Common use cases +## Casos de uso comunes -Router events enable many practical features in real-world applications. Here are some common patterns that are used with router events. +Los eventos del router habilitan muchas características prácticas en aplicaciones del mundo real. Aquí hay algunos patrones comunes que se usan con eventos del router. -### Loading indicators +### Indicadores de carga -Show loading indicators during navigation: +Mostrar indicadores de carga durante la navegación: ```angular-ts import { Component, inject } from '@angular/core'; @@ -112,9 +112,9 @@ export class AppComponent { } ``` -### Analytics tracking +### Seguimiento de analíticas -Track page views for analytics: +Rastrear vistas de página para analíticas: ```typescript import { Component, inject, signal, effect } from '@angular/core'; @@ -128,9 +128,9 @@ export class AnalyticsService { startTracking() { this.router.events.pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(event => { - // Track page views when URL changes + // Rastrear vistas de página cuando cambia la URL if (event instanceof NavigationEnd) { - // Send page view to analytics + // Enviar vista de página a analíticas this.analytics.trackPageView(url); } }); @@ -144,9 +144,9 @@ export class AnalyticsService { } ``` -### Error handling +### Manejo de errores -Handle navigation errors gracefully and provide user feedback: +Manejar errores de navegación con gracia y proporcionar retroalimentación al usuario: ```angular-ts import { Component, inject, signal } from '@angular/core'; @@ -189,55 +189,55 @@ export class ErrorHandlerComponent { } ``` -## All router events +## Todos los eventos del router -For reference, here is the complete list of all router events available in Angular. These events are organized by category and listed in the order they typically occur during navigation. +Para referencia, aquí está la lista completa de todos los eventos del router disponibles en Angular. Estos eventos están organizados por categoría y listados en el orden en que típicamente ocurren durante la navegación. -### Navigation events +### Eventos de navegación -These events track the core navigation process from start through route recognition, guard checks, and data resolution. They provide visibility into each phase of the navigation lifecycle. +Estos eventos rastrean el proceso central de navegación desde el inicio a través del reconocimiento de rutas, verificación de guards y resolución de datos. Proporcionan visibilidad en cada fase del ciclo de vida de navegación. -| Event | Description | +| Evento | Descripción | | --------------------------------------------------------- | --------------------------------------------------------------- | -| [`NavigationStart`](api/router/NavigationStart) | Occurs when navigation starts | -| [`RouteConfigLoadStart`](api/router/RouteConfigLoadStart) | Occurs before lazy loading a route configuration | -| [`RouteConfigLoadEnd`](api/router/RouteConfigLoadEnd) | Occurs after a lazy-loaded route configuration loads | -| [`RoutesRecognized`](api/router/RoutesRecognized) | Occurs when the router parses the URL and recognizes the routes | -| [`GuardsCheckStart`](api/router/GuardsCheckStart) | Occurs at the start of the guard phase | -| [`GuardsCheckEnd`](api/router/GuardsCheckEnd) | Occurs at the end of the guard phase | -| [`ResolveStart`](api/router/ResolveStart) | Occurs at the start of the resolve phase | -| [`ResolveEnd`](api/router/ResolveEnd) | Occurs at the end of the resolve phase | +| [`NavigationStart`](api/router/NavigationStart) | Ocurre cuando comienza la navegación | +| [`RouteConfigLoadStart`](api/router/RouteConfigLoadStart) | Ocurre antes de cargar de forma diferida una configuración de ruta | +| [`RouteConfigLoadEnd`](api/router/RouteConfigLoadEnd) | Ocurre después de que se carga una configuración de ruta con lazy loading | +| [`RoutesRecognized`](api/router/RoutesRecognized) | Ocurre cuando el router parsea la URL y reconoce las rutas | +| [`GuardsCheckStart`](api/router/GuardsCheckStart) | Ocurre al inicio de la fase de guards | +| [`GuardsCheckEnd`](api/router/GuardsCheckEnd) | Ocurre al final de la fase de guards | +| [`ResolveStart`](api/router/ResolveStart) | Ocurre al inicio de la fase de resolve | +| [`ResolveEnd`](api/router/ResolveEnd) | Ocurre al final de la fase de resolve | -### Activation events +### Eventos de activación -These events occur during the activation phase when route components are being instantiated and initialized. Activation events fire for each route in the route tree, including parent and child routes. +Estos eventos ocurren durante la fase de activación cuando los componentes de ruta están siendo instanciados e inicializados. Los eventos de activación se disparan para cada ruta en el árbol de rutas, incluyendo rutas padre e hijo. -| Event | Description | +| Evento | Descripción | | --------------------------------------------------------- | --------------------------------------------- | -| [`ActivationStart`](api/router/ActivationStart) | Occurs at the start of route activation | -| [`ChildActivationStart`](api/router/ChildActivationStart) | Occurs at the start of child route activation | -| [`ActivationEnd`](api/router/ActivationEnd) | Occurs at the end of route activation | -| [`ChildActivationEnd`](api/router/ChildActivationEnd) | Occurs at the end of child route activation | +| [`ActivationStart`](api/router/ActivationStart) | Ocurre al inicio de la activación de ruta | +| [`ChildActivationStart`](api/router/ChildActivationStart) | Ocurre al inicio de la activación de ruta hijo | +| [`ActivationEnd`](api/router/ActivationEnd) | Ocurre al final de la activación de ruta | +| [`ChildActivationEnd`](api/router/ChildActivationEnd) | Ocurre al final de la activación de ruta hijo | -### Navigation completion events +### Eventos de finalización de navegación -These events represent the final outcome of a navigation attempt. Every navigation will end with exactly one of these events, indicating whether it succeeded, was cancelled, failed, or was skipped. +Estos eventos representan el resultado final de un intento de navegación. Cada navegación terminará con exactamente uno de estos eventos, indicando si tuvo éxito, fue cancelada, falló o fue omitida. -| Event | Description | +| Evento | Descripción | | --------------------------------------------------- | ------------------------------------------------------------------- | -| [`NavigationEnd`](api/router/NavigationEnd) | Occurs when navigation ends successfully | -| [`NavigationCancel`](api/router/NavigationCancel) | Occurs when the router cancels navigation | -| [`NavigationError`](api/router/NavigationError) | Occurs when navigation fails due to an unexpected error | -| [`NavigationSkipped`](api/router/NavigationSkipped) | Occurs when the router skips navigation (e.g., same URL navigation) | +| [`NavigationEnd`](api/router/NavigationEnd) | Ocurre cuando la navegación termina exitosamente | +| [`NavigationCancel`](api/router/NavigationCancel) | Ocurre cuando el router cancela la navegación | +| [`NavigationError`](api/router/NavigationError) | Ocurre cuando la navegación falla debido a un error inesperado | +| [`NavigationSkipped`](api/router/NavigationSkipped) | Ocurre cuando el router omite la navegación (por ejemplo, navegación a la misma URL) | -### Other events +### Otros eventos -There is one additional event that occurs outside the main navigation lifecycle, but it is still part of the router's event system. +Hay un evento adicional que ocurre fuera del ciclo de vida principal de navegación, pero aún es parte del sistema de eventos del router. -| Event | Description | +| Evento | Descripción | | ----------------------------- | ----------------------- | -| [`Scroll`](api/router/Scroll) | Occurs during scrolling | +| [`Scroll`](api/router/Scroll) | Ocurre durante el scrolling | -## Next steps +## Próximos pasos -Learn more about [route guards](/guide/routing/route-guards) and [common router tasks](/guide/routing/common-router-tasks). +Aprende más sobre [guards de ruta](/guide/routing/route-guards) y [tareas comunes del router](/guide/routing/common-router-tasks). diff --git a/adev-es/src/content/guide/routing/navigate-to-routes.en.md b/adev-es/src/content/guide/routing/navigate-to-routes.en.md new file mode 100644 index 0000000..3602045 --- /dev/null +++ b/adev-es/src/content/guide/routing/navigate-to-routes.en.md @@ -0,0 +1,171 @@ +# Navigate to routes + +The RouterLink directive is Angular's declarative approach to navigation. It allows you to use standard anchor elements (``) that seamlessly integrate with Angular's routing system. + +## How to use RouterLink + +Instead of using regular anchor elements `` with an `href` attribute, you add a RouterLink directive with the appropriate path in order to leverage Angular routing. +```angular-ts +import {RouterLink} from '@angular/router'; +@Component({ + template: ` + + ` + imports: [RouterLink], + ... +}) +export class App {} +``` + +### Using absolute or relative links + +**Relative URLs** in Angular routing allow you to define navigation paths relative to the current route's location. This is in contrast to **absolute URLs** which contain the full path with the protocol (e.g., `http://`) and the **root domain** (e.g., `google.com`). + +```angular-html + +Angular Essentials Guide + + +Angular Essentials Guide +``` + +In this example, the first example contains the full path with the protocol (i.e., `https://`) and the root domain (i.e., `angular.dev`) explicitly defined for the essentials page. In contrast, the second example assumes the user is already on the correct root domain for `/essentials`. + +Generally speaking, relative URLs are preferred because they are more maintainable across applications because they don't need to know their absolute position within the routing hierarchy. + +### How relative URLs work + +Angular routing has two syntaxes for defining relative URLs: strings and arrays. + +```angular-html + +Dashboard +Dashboard +``` + +HELPFUL: Passing a string is the most common way to define relative URLs. + +When you need to define dynamic parameters in a relative URL, use the array syntax: + +```angular-html +Current User +``` + +In addition, Angular routing allows you specify whether you want the path to be relative to the current URL or to the root domain based on whether the relative path is prefixed with a forward slash (`/`) or not. + +For example, if the user is on `example.com/settings`, here is how different relative paths can be defined for various scenarios: + +```angular-html + +Notifications +Notifications + + +User 456 +Current User" +``` + +## Programmatic navigation to routes + +While `RouterLink` handles declarative navigation in templates, Angular provides programmatic navigation for scenarios where you need to navigate based on logic, user actions, or application state. By injecting `Router`, you can dynamically navigate to routes, pass parameters, and control navigation behavior in your TypeScript code. + +### `router.navigate()` + +You can use the `router.navigate()` method to programmatically navigate between routes by specifying a URL path array. + +```angular-ts +import { Router } from '@angular/router'; + +@Component({ + selector: 'app-dashboard', + template: ` + + ` +}) +export class AppDashboard { + private router = inject(Router); + + navigateToProfile() { + // Standard navigation + this.router.navigate(['/profile']); + + // With route parameters + this.router.navigate(['/users', userId]); + + // With query parameters + this.router.navigate(['/search'], { + queryParams: { category: 'books', sort: 'price' } + }); + } +} +``` + +`router.navigate()` supports both simple and complex routing scenarios, allowing you to pass route parameters, [query parameters](/guide/routing/read-route-state#query-parameters), and control navigation behavior. + +You can also build dynamic navigation paths relative to your component's location in the routing tree using the `relativeTo` option. + +```angular-ts +import { Router, ActivatedRoute } from '@angular/router'; + +@Component({ + selector: 'app-user-detail', + template: ` + + + ` +}) +export class UserDetailComponent { + private route = inject(ActivatedRoute); + private router = inject(Router); + + constructor() {} + + // Navigate to a sibling route + navigateToEdit() { + // From: /users/123 + // To: /users/123/edit + this.router.navigate(['edit'], { relativeTo: this.route }); + } + + // Navigate to parent + navigateToParent() { + // From: /users/123 + // To: /users + this.router.navigate(['..'], { relativeTo: this.route }); + } +} +``` + +### `router.navigateByUrl()` + +The `router.navigateByUrl()` method provides a direct way to programmatically navigate using URL path strings rather than array segments. This method is ideal when you have a full URL path and need to perform absolute navigation, especially when working with externally provided URLs or deep linking scenarios. + +```angular-ts +// Standard route navigation +router.navigateByUrl('/products); + +// Navigate to nested route +router.navigateByUrl('/products/featured'); + +// Complete URL with parameters and fragment +router.navigateByUrl('/products/123?view=details#reviews'); + +// Navigate with query parameters +router.navigateByUrl('/search?category=books&sortBy=price'); +``` + +In the event you need to replace the current URL in history, `navigateByUrl` also accepts a configuration object that has a `replaceUrl` option. + +```angular-ts +// Replace current URL in history +router.navigateByUrl('/checkout', { + replaceUrl: true +}); +``` + +## Next steps + +Learn how to [read route state](/guide/routing/read-route-state) to create responsive and context-aware components. diff --git a/adev-es/src/content/guide/routing/navigate-to-routes.md b/adev-es/src/content/guide/routing/navigate-to-routes.md index 78daed1..97adda3 100644 --- a/adev-es/src/content/guide/routing/navigate-to-routes.md +++ b/adev-es/src/content/guide/routing/navigate-to-routes.md @@ -1,10 +1,10 @@ -# Navigate to routes +# Navegar a rutas -The RouterLink directive is Angular's declarative approach to navigation. It allows you to use standard anchor elements (``) that seamlessly integrate with Angular's routing system. +La directiva RouterLink es el enfoque declarativo de Angular para la navegación. Te permite usar elementos anchor estándar (``) que se integran sin problemas con el sistema de enrutamiento en Angular. -## How to use RouterLink +## Cómo usar RouterLink -Instead of using regular anchor elements `` with an `href` attribute, you add a RouterLink directive with the appropriate path in order to leverage Angular routing. +En lugar de usar elementos anchor regulares `` con un atributo `href`, agregas una directiva RouterLink con la ruta apropiada para aprovechar el enrutamiento en Angular. ```angular-ts import {RouterLink} from '@angular/router'; @Component({ @@ -20,61 +20,61 @@ import {RouterLink} from '@angular/router'; export class App {} ``` -### Using absolute or relative links +### Usando enlaces absolutos o relativos -**Relative URLs** in Angular routing allow you to define navigation paths relative to the current route's location. This is in contrast to **absolute URLs** which contain the full path with the protocol (e.g., `http://`) and the **root domain** (e.g., `google.com`). +Las **URLs relativas** en el enrutamiento en Angular te permiten definir rutas de navegación relativas a la ubicación de la ruta actual. Esto contrasta con las **URLs absolutas** que contienen la ruta completa con el protocolo (por ejemplo, `http://`) y el **dominio raíz** (por ejemplo, `google.com`). ```angular-html - + Angular Essentials Guide - + Angular Essentials Guide ``` -In this example, the first example contains the full path with the protocol (i.e., `https://`) and the root domain (i.e., `angular.dev`) explicitly defined for the essentials page. In contrast, the second example assumes the user is already on the correct root domain for `/essentials`. +En este ejemplo, el primer ejemplo contiene la ruta completa con el protocolo (es decir, `https://`) y el dominio raíz (es decir, `angular.dev`) explícitamente definidos para la página de essentials. En contraste, el segundo ejemplo asume que el usuario ya está en el dominio raíz correcto para `/essentials`. -Generally speaking, relative URLs are preferred because they are more maintainable across applications because they don’t need to know their absolute position within the routing hierarchy. +En términos generales, se prefieren las URLs relativas porque son más mantenibles en todas las aplicaciones porque no necesitan conocer su posición absoluta dentro de la jerarquía de enrutamiento. -### How relative URLs work +### Cómo funcionan las URLs relativas -Angular routing has two syntaxes for defining relative URLs: strings and arrays. +El enrutamiento en Angular tiene dos sintaxis para definir URLs relativas: strings y arrays. ```angular-html - + Dashboard Dashboard ``` -HELPFUL: Passing a string is the most common way to define relative URLs. +ÚTIL: Pasar un string es la forma más común de definir URLs relativas. -When you need to define dynamic parameters in a relative URL, use the array syntax: +Cuando necesitas definir parámetros dinámicos en una URL relativa, usa la sintaxis de array: ```angular-html Current User ``` -In addition, Angular routing allows you specify whether you want the path to be relative to the current URL or to the root domain based on whether the relative path is prefixed with a forward slash (`/`) or not. +Además, el enrutamiento en Angular te permite especificar si quieres que la ruta sea relativa a la URL actual o al dominio raíz según si la ruta relativa tiene o no el prefijo de barra diagonal (`/`). -For example, if the user is on `example.com/settings`, here is how different relative paths can be defined for various scenarios: +Por ejemplo, si el usuario está en `example.com/settings`, aquí está cómo se pueden definir diferentes rutas relativas para varios escenarios: ```angular-html - + Notifications Notifications - + User 456 -Current User” +Current User" ``` -## Programmatic navigation to routes +## Navegación programática a rutas -While `RouterLink` handles declarative navigation in templates, Angular provides programmatic navigation for scenarios where you need to navigate based on logic, user actions, or application state. By injecting `Router`, you can dynamically navigate to routes, pass parameters, and control navigation behavior in your TypeScript code. +Mientras que `RouterLink` maneja la navegación declarativa en templates, Angular proporciona navegación programática para escenarios donde necesitas navegar basándote en lógica, acciones del usuario o estado de la aplicación. Al inyectar `Router`, puedes navegar dinámicamente a rutas, pasar parámetros y controlar el comportamiento de navegación en tu código TypeScript. ### `router.navigate()` -You can use the `router.navigate()` method to programmatically navigate between routes by specifying a URL path array. +Puedes usar el método `router.navigate()` para navegar programáticamente entre rutas especificando un array de ruta URL. ```angular-ts import { Router } from '@angular/router'; @@ -89,13 +89,13 @@ export class AppDashboard { private router = inject(Router); navigateToProfile() { - // Standard navigation + // Navegación estándar this.router.navigate(['/profile']); - // With route parameters + // Con parámetros de ruta this.router.navigate(['/users', userId]); - // With query parameters + // Con parámetros de consulta this.router.navigate(['/search'], { queryParams: { category: 'books', sort: 'price' } }); @@ -103,9 +103,9 @@ export class AppDashboard { } ``` -`router.navigate()` supports both simple and complex routing scenarios, allowing you to pass route parameters, [query parameters](/guide/routing/read-route-state#query-parameters), and control navigation behavior. +`router.navigate()` soporta escenarios de enrutamiento simples y complejos, permitiéndote pasar parámetros de ruta, [parámetros de consulta](/guide/routing/read-route-state#query-parameters), y controlar el comportamiento de navegación. -You can also build dynamic navigation paths relative to your component’s location in the routing tree using the `relativeTo` option. +También puedes construir rutas de navegación dinámicas relativas a la ubicación de tu componente en el árbol de enrutamiento usando la opción `relativeTo`. ```angular-ts import { Router, ActivatedRoute } from '@angular/router'; @@ -123,17 +123,17 @@ export class UserDetailComponent { constructor() {} - // Navigate to a sibling route + // Navegar a una ruta hermana navigateToEdit() { - // From: /users/123 - // To: /users/123/edit + // Desde: /users/123 + // A: /users/123/edit this.router.navigate(['edit'], { relativeTo: this.route }); } - // Navigate to parent + // Navegar al padre navigateToParent() { - // From: /users/123 - // To: /users + // Desde: /users/123 + // A: /users this.router.navigate(['..'], { relativeTo: this.route }); } } @@ -141,31 +141,31 @@ export class UserDetailComponent { ### `router.navigateByUrl()` -The `router.navigateByUrl()` method provides a direct way to programmatically navigate using URL path strings rather than array segments. This method is ideal when you have a full URL path and need to perform absolute navigation, especially when working with externally provided URLs or deep linking scenarios. +El método `router.navigateByUrl()` proporciona una forma directa de navegar programáticamente usando strings de ruta URL en lugar de segmentos de array. Este método es ideal cuando tienes una ruta URL completa y necesitas realizar navegación absoluta, especialmente cuando trabajas con URLs proporcionadas externamente o escenarios de deep linking. ```angular-ts -// Standard route navigation +// Navegación de ruta estándar router.navigateByUrl('/products); -// Navigate to nested route +// Navegar a ruta anidada router.navigateByUrl('/products/featured'); -// Complete URL with parameters and fragment +// URL completa con parámetros y fragmento router.navigateByUrl('/products/123?view=details#reviews'); -// Navigate with query parameters +// Navegar con parámetros de consulta router.navigateByUrl('/search?category=books&sortBy=price'); ``` -In the event you need to replace the current URL in history, `navigateByUrl` also accepts a configuration object that has a `replaceUrl` option. +En caso de que necesites reemplazar la URL actual en el historial, `navigateByUrl` también acepta un objeto de configuración que tiene una opción `replaceUrl`. ```angular-ts -// Replace current URL in history +// Reemplazar URL actual en el historial router.navigateByUrl('/checkout', { replaceUrl: true }); ``` -## Next steps +## Próximos pasos -Learn how to [read route state](/guide/routing/read-route-state) to create responsive and context-aware components. +Aprende cómo [leer estado de ruta](/guide/routing/read-route-state) para crear componentes responsivos y conscientes del contexto. diff --git a/adev-es/src/content/guide/routing/overview.en.md b/adev-es/src/content/guide/routing/overview.en.md new file mode 100644 index 0000000..e219535 --- /dev/null +++ b/adev-es/src/content/guide/routing/overview.en.md @@ -0,0 +1,32 @@ + +Routing helps you change what the user sees in a single-page app. + + +Angular Router (`@angular/router`) is the official library for managing navigation in Angular applications and a core part of the framework. It is included by default in all projects created by Angular CLI. + +## Why is routing necessary in a SPA? + +When you navigate to a URL in your web browser, the browser normally makes a network request to a web server and displays the returned HTML page. When you navigate to a different URL, such as clicking a link, the browser makes another network request and replaces the entire page with a new one. + +A single-page application (SPA) differs in that the browser only makes a request to a web server for the first page, the `index.html`. After that, a client-side router takes over, controlling which content displays based on the URL. When a user navigates to a different URL, the router updates the page's content in place without triggering a full-page reload. + +## How Angular manages routing + +Routing in Angular is comprised of three primary parts: + +1. **Routes** define which component displays when a user visits a specific URL. +2. **Outlets** are placeholders in your templates that dynamically load and render components based on the active route. +3. **Links** provide a way for users to navigate between different routes in your application without triggering a full page reload. + +In addition, the Angular Routing library offers additional functionality such as: + +- Nested routes +- Programmatic navigation +- Route params, queries and wildcards +- Activated route information with `ActivatedRoute` +- View transition effects +- Navigation guards + +## Next steps + +Learn about how you can [define routes using Angular router](/guide/routing/define-routes). diff --git a/adev-es/src/content/guide/routing/overview.md b/adev-es/src/content/guide/routing/overview.md index e219535..1db715d 100644 --- a/adev-es/src/content/guide/routing/overview.md +++ b/adev-es/src/content/guide/routing/overview.md @@ -1,32 +1,32 @@ - -Routing helps you change what the user sees in a single-page app. + +El enrutamiento te ayuda a cambiar lo que el usuario ve en una aplicación de página única. -Angular Router (`@angular/router`) is the official library for managing navigation in Angular applications and a core part of the framework. It is included by default in all projects created by Angular CLI. +Angular Router (`@angular/router`) es la librería oficial para gestionar la navegación en aplicaciones de Angular y una parte fundamental del framework. Se incluye de forma predeterminada en todos los proyectos creados por Angular CLI. -## Why is routing necessary in a SPA? +## ¿Por qué es necesario el enrutamiento en una SPA? -When you navigate to a URL in your web browser, the browser normally makes a network request to a web server and displays the returned HTML page. When you navigate to a different URL, such as clicking a link, the browser makes another network request and replaces the entire page with a new one. +Cuando navegas a una URL en tu navegador web, el navegador normalmente hace una petición de red a un servidor web y muestra la página HTML devuelta. Cuando navegas a una URL diferente, como hacer clic en un enlace, el navegador hace otra petición de red y reemplaza toda la página con una nueva. -A single-page application (SPA) differs in that the browser only makes a request to a web server for the first page, the `index.html`. After that, a client-side router takes over, controlling which content displays based on the URL. When a user navigates to a different URL, the router updates the page's content in place without triggering a full-page reload. +Una aplicación de página única (SPA) difiere en que el navegador solo hace una petición a un servidor web para la primera página, el `index.html`. Después de eso, un router del lado del cliente toma el control, controlando qué contenido se muestra según la URL. Cuando un usuario navega a una URL diferente, el router actualiza el contenido de la página en el lugar sin disparar una recarga completa de la página. -## How Angular manages routing +## Cómo Angular gestiona el enrutamiento -Routing in Angular is comprised of three primary parts: +El enrutamiento en Angular se compone de tres partes principales: -1. **Routes** define which component displays when a user visits a specific URL. -2. **Outlets** are placeholders in your templates that dynamically load and render components based on the active route. -3. **Links** provide a way for users to navigate between different routes in your application without triggering a full page reload. +1. **Routes** definen qué componente se muestra cuando un usuario visita una URL específica. +2. **Outlets** son marcadores de posición en tus plantillas que cargan y renderizan dinámicamente componentes según la ruta activa. +3. **Links** proporcionan una forma para que los usuarios naveguen entre diferentes rutas en tu aplicación sin disparar una recarga completa de la página. -In addition, the Angular Routing library offers additional functionality such as: +Además, la librería de enrutamiento en Angular ofrece funcionalidad adicional como: -- Nested routes -- Programmatic navigation -- Route params, queries and wildcards -- Activated route information with `ActivatedRoute` -- View transition effects +- Rutas anidadas +- Navegación programática +- Parámetros de ruta, consultas y comodines +- Información de ruta activada con `ActivatedRoute` +- Efectos de transición de vista - Navigation guards -## Next steps +## Próximos pasos -Learn about how you can [define routes using Angular router](/guide/routing/define-routes). +Aprende sobre cómo puedes [definir rutas usando Angular router](/guide/routing/define-routes). diff --git a/adev-es/src/content/guide/routing/read-route-state.en.md b/adev-es/src/content/guide/routing/read-route-state.en.md new file mode 100644 index 0000000..4e3807b --- /dev/null +++ b/adev-es/src/content/guide/routing/read-route-state.en.md @@ -0,0 +1,288 @@ +# Read route state + +Angular Router allows you to read and use information associated with a route to create responsive and context-aware components. + +## Get information about the current route with ActivatedRoute + +`ActivatedRoute` is a service from `@angular/router` that provides all the information associated with the current route. + +```angular-ts +import { Component } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +@Component({ + selector: 'app-product', +}) +export class ProductComponent { + private activatedRoute = inject(ActivatedRoute); + + constructor() { + console.log(this.activatedRoute); + } +} +``` + +The `ActivatedRoute` can provide different information about the route. Some common properties include: + +| Property | Details | +| :------------ | :-------------------------------------------------------------------------------------------------------------------------------- | +| `url` | An `Observable` of the route paths, represented as an array of strings for each part of the route path. | +| `data` | An `Observable` that contains the `data` object provided for the route. Also contains any resolved values from the resolve guard. | +| `params` | An `Observable` that contains the required and optional parameters specific to the route. | +| `queryParams` | An `Observable` that contains the query parameters available to all routes. | + +Check out the [`ActivatedRoute` API docs](/api/router/ActivatedRoute) for a complete list of what you can access with in the route. + +## Understanding route snapshots + +Page navigations are events over time, and you can access the router state at a given time by retrieving a route snapshot. + +Route snapshots contain essential information about the route, including its parameters, data, and child routes. In addition, snapshots are static and will not reflect future changes. + +Here's an example of how you'd access a route snapshot: + +```angular-ts +import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router'; + +@Component({ ... }) +export class UserProfileComponent { + readonly userId: string; + private route = inject(ActivatedRoute); + + constructor() { + // Example URL: https://www.angular.dev/users/123?role=admin&status=active#contact + + // Access route parameters from snapshot + this.userId = this.route.snapshot.paramMap.get('id'); + + // Access multiple route elements + const snapshot = this.route.snapshot; + console.log({ + url: snapshot.url, // https://www.angular.dev + // Route parameters object: {id: '123'} + params: snapshot.params, + // Query parameters object: {role: 'admin', status: 'active'} + queryParams: snapshot.queryParams, // Query parameters + }); + } +} +``` + +Check out the [`ActivatedRoute` API docs](/api/router/ActivatedRoute) and [`ActivatedRouteSnapshot` API docs](/api/router/ActivatedRouteSnapshot) for a complete list of all properties you can access. + +## Reading parameters on a route + +There are two types of parameters that developers can utilize from a route: route and query parameters. + +### Route Parameters + +Route parameters allow you to pass data to a component through the URL. This is useful when you want to display specific content based on an identifier in the URL, like a user ID or a product ID. + +You can [define route parameters](/guide/routing/define-routes#define-url-paths-with-route-parameters) by prefixing the parameter name with a colon (`:`). + +```angular-ts +import { Routes } from '@angular/router'; +import { ProductComponent } from './product/product.component'; + +const routes: Routes = [ + { path: 'product/:id', component: ProductComponent } +]; +``` + +You can access parameters by subscribing to `route.params`. + +```angular-ts +import { Component, inject, signal } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +@Component({ + selector: 'app-product-detail', + template: `

Product Details: {{ productId() }}

`, +}) +export class ProductDetailComponent { + productId = signal(''); + private activatedRoute = inject(ActivatedRoute); + + constructor() { + // Access route parameters + this.activatedRoute.params.subscribe((params) => { + this.productId.set(params['id']); + }); + } +} +``` + +### Query Parameters + +[Query parameters](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) provide a flexible way to pass optional data through URLs without affecting the route structure. Unlike route parameters, query parameters can persist across navigation events and are perfect for handling filtering, sorting, pagination, and other stateful UI elements. + +```angular-ts +// Single parameter structure +// /products?category=electronics +router.navigate(['/products'], { + queryParams: { category: 'electronics' } +}); + +// Multiple parameters +// /products?category=electronics&sort=price&page=1 +router.navigate(['/products'], { + queryParams: { + category: 'electronics', + sort: 'price', + page: 1 + } +}); +``` + +You can access query parameters with `route.queryParams`. + +Here is an example of a `ProductListComponent` that updates the query parameters that affect how it displays a list of products: + +```angular-ts +import { ActivatedRoute, Router } from '@angular/router'; + +@Component({ + selector: 'app-product-list', + template: ` +
+ + +
+ ` +}) +export class ProductListComponent implements OnInit { + private route = inject(ActivatedRoute); + private router = inject(Router); + + constructor() { + // Access query parameters reactively + this.route.queryParams.subscribe(params => { + const sort = params['sort'] || 'price'; + const page = Number(params['page']) || 1; + this.loadProducts(sort, page); + }); + } + + updateSort(event: Event) { + const sort = (event.target as HTMLSelectElement).value; + // Update URL with new query parameter + this.router.navigate([], { + queryParams: { sort }, + queryParamsHandling: 'merge' // Preserve other query parameters + }); + } +} +``` + +In this example, users can use a select element to sort the product list by name or price. The associated change handler updates the URL's query parameters, which in turn triggers a change event that can read the updated query parameters and update the product list. + +For more information, check out the [official docs on QueryParamsHandling](/api/router/QueryParamsHandling). + +## Detect active current route with RouterLinkActive + +You can use the `RouterLinkActive` directive to dynamically style navigation elements based on the current active route. This is common in navigation elements to inform users what the active route is. + +```angular-html + +``` + +In this example, Angular Router will apply the `active-button` class to the correct anchor link and `ariaCurrentWhenActive` to `page` when the URL matches the corresponding `routerLink`. + +If you need to add multiple classes onto the element, you can use either a space-separated string or an array: + +```angular-html + +Bob + + +Bob +``` + +When you specify a value for routerLinkActive, you are also defining the same value for `ariaCurrentWhenActive`. This makes sure that visually impaired users (which may not perceive the different styling being applied) can also identify the active button. + +If you want to define a different value for aria, you'll need to explicitly set the value using the `ariaCurrentWhenActive` directive. + +### Route matching strategy + +By default, `RouterLinkActive` considers any ancestors in the route a match. + +```angular-html + + User + + + Role + +``` + +When the user visits `/user/jane/role/admin`, both links would have the `active-link` class. + +### Only apply RouterLinkActive on exact route matches + +If you only want to apply the class on an exact match, you need to provide the `routerLinkActiveOptions` directive with a configuration object that contains the value `exact: true`. + +```angular-html + + User + + + Role + +``` + +If you want to be more precise in how a route is matched, it's worth noting that `exact: true` is actually syntactic sugar for the full set of matching options: + +```angular-ts +// `exact: true` is equivalent to +{ + paths: 'exact', + fragment: 'ignored', + matrixParams: 'ignored', + queryParams: 'exact', +} + +// `exact: false` is equivalent +{ + paths: 'subset', + fragment: 'ignored', + matrixParams: 'ignored', + queryParams: 'subset', +} +``` + +For more information, check out the official docs for [isActiveMatchOptions](/api/router/IsActiveMatchOptions). + +### Apply RouterLinkActive to an ancestor + +The RouterLinkActive directive can also be applied to an ancestor element in order to allow developers to style the elements as desired. + +```angular-html +
+ Jim + Bob +
+``` + +For more information, check out the [API docs for RouterLinkActive](/api/router/RouterLinkActive). diff --git a/adev-es/src/content/guide/routing/read-route-state.md b/adev-es/src/content/guide/routing/read-route-state.md index 2279405..9b57327 100644 --- a/adev-es/src/content/guide/routing/read-route-state.md +++ b/adev-es/src/content/guide/routing/read-route-state.md @@ -1,10 +1,10 @@ -# Read route state +# Leer estado de ruta -Angular Router allows you to read and use information associated with a route to create responsive and context-aware components. +El Router de Angular te permite leer y usar información asociada con una ruta para crear componentes responsivos y conscientes del contexto. -## Get information about the current route with ActivatedRoute +## Obtener información sobre la ruta actual con ActivatedRoute -`ActivatedRoute` is a service from `@angular/router` that provides all the information associated with the current route. +`ActivatedRoute` es un servicio de `@angular/router` que proporciona toda la información asociada con la ruta actual. ```angular-ts import { Component } from '@angular/core'; @@ -22,24 +22,24 @@ export class ProductComponent { } ``` -The `ActivatedRoute` can provide different information about the route. Some common properties include: +El `ActivatedRoute` puede proporcionar diferente información sobre la ruta. Algunas propiedades comunes incluyen: -| Property | Details | -| :------------ | :-------------------------------------------------------------------------------------------------------------------------------- | -| `url` | An `Observable` of the route paths, represented as an array of strings for each part of the route path. | -| `data` | An `Observable` that contains the `data` object provided for the route. Also contains any resolved values from the resolve guard. | -| `params` | An `Observable` that contains the required and optional parameters specific to the route. | -| `queryParams` | An `Observable` that contains the query parameters available to all routes. | +| Propiedad | Detalles | +| :------------ | :-------------------------------------------------------------------------------------------------------------------------------------------- | +| `url` | Un `Observable` de las rutas de ruta, representadas como un array de strings para cada parte de la ruta de ruta. | +| `data` | Un `Observable` que contiene el objeto `data` proporcionado para la ruta. También contiene cualquier valor resuelto del guard de resolución. | +| `params` | Un `Observable` que contiene los parámetros requeridos y opcionales específicos de la ruta. | +| `queryParams` | Un `Observable` que contiene los parámetros de consulta disponibles para todas las rutas. | -Check out the [`ActivatedRoute` API docs](/api/router/ActivatedRoute) for a complete list of what you can access with in the route. +Consulta los [docs de la API de `ActivatedRoute`](/api/router/ActivatedRoute) para una lista completa de lo que puedes acceder dentro de la ruta. -## Understanding route snapshots +## Entendiendo snapshots de ruta -Page navigations are events over time, and you can access the router state at a given time by retrieving a route snapshot. +Las navegaciones de página son eventos a lo largo del tiempo, y puedes acceder al estado del router en un momento dado recuperando un snapshot de ruta. -Route snapshots contain essential information about the route, including its parameters, data, and child routes. In addition, snapshots are static and will not reflect future changes. +Los snapshots de ruta contienen información esencial sobre la ruta, incluyendo sus parámetros, datos y rutas hijas. Además, los snapshots son estáticos y no reflejarán cambios futuros. -Here’s an example of how you’d access a route snapshot: +Aquí hay un ejemplo de cómo accederías a un snapshot de ruta: ```angular-ts import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router'; @@ -50,35 +50,35 @@ export class UserProfileComponent { private route = inject(ActivatedRoute); constructor() { - // Example URL: https://www.angular.dev/users/123?role=admin&status=active#contact + // URL de ejemplo: https://www.angular.dev/users/123?role=admin&status=active#contact - // Access route parameters from snapshot + // Acceder a parámetros de ruta desde snapshot this.userId = this.route.snapshot.paramMap.get('id'); - // Access multiple route elements + // Acceder a múltiples elementos de ruta const snapshot = this.route.snapshot; console.log({ url: snapshot.url, // https://www.angular.dev - // Route parameters object: {id: '123'} + // Objeto de parámetros de ruta: {id: '123'} params: snapshot.params, - // Query parameters object: {role: 'admin', status: 'active'} - queryParams: snapshot.queryParams, // Query parameters + // Objeto de parámetros de consulta: {role: 'admin', status: 'active'} + queryParams: snapshot.queryParams, // Parámetros de consulta }); } } ``` -Check out the [`ActivatedRoute` API docs](/api/router/ActivatedRoute) and [`ActivatedRouteSnapshot` API docs](/api/router/ActivatedRouteSnapshot) for a complete list of all properties you can access. +Consulta los [docs de la API de `ActivatedRoute`](/api/router/ActivatedRoute) y los [docs de la API de `ActivatedRouteSnapshot`](/api/router/ActivatedRouteSnapshot) para una lista completa de todas las propiedades que puedes acceder. -## Reading parameters on a route +## Leyendo parámetros en una ruta -There are two types of parameters that developers can utilize from a route: route and query parameters. +Hay dos tipos de parámetros que los desarrolladores pueden utilizar desde una ruta: parámetros de ruta y parámetros de consulta. -### Route Parameters +### Parámetros de ruta -Route parameters allow you to pass data to a component through the URL. This is useful when you want to display specific content based on an identifier in the URL, like a user ID or a product ID. +Los parámetros de ruta te permiten pasar datos a un componente a través de la URL. Esto es útil cuando quieres mostrar contenido específico basado en un identificador en la URL, como un ID de usuario o un ID de producto. -You can [define route parameters](/guide/routing/define-routes#define-url-paths-with-route-parameters) by prefixing the parameter name with a colon (`:`). +Puedes [definir parámetros de ruta](/guide/routing/define-routes#define-url-paths-with-route-parameters) prefijando el nombre del parámetro con dos puntos (`:`). ```angular-ts import { Routes } from '@angular/router'; @@ -89,7 +89,7 @@ const routes: Routes = [ ]; ``` -You can access parameters by subscribing to `route.params`. +Puedes acceder a los parámetros suscribiéndote a `route.params`. ```angular-ts import { Component, inject, signal } from '@angular/core'; @@ -104,7 +104,7 @@ export class ProductDetailComponent { private activatedRoute = inject(ActivatedRoute); constructor() { - // Access route parameters + // Acceder a parámetros de ruta this.activatedRoute.params.subscribe((params) => { this.productId.set(params['id']); }); @@ -112,18 +112,18 @@ export class ProductDetailComponent { } ``` -### Query Parameters +### Parámetros de consulta -[Query parameters](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) provide a flexible way to pass optional data through URLs without affecting the route structure. Unlike route parameters, query parameters can persist across navigation events and are perfect for handling filtering, sorting, pagination, and other stateful UI elements. +Los [parámetros de consulta](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) proporcionan una forma flexible de pasar datos opcionales a través de URLs sin afectar la estructura de la ruta. A diferencia de los parámetros de ruta, los parámetros de consulta pueden persistir a través de eventos de navegación y son perfectos para manejar filtrado, ordenamiento, paginación y otros elementos UI con estado. ```angular-ts -// Single parameter structure +// Estructura de parámetro único // /products?category=electronics router.navigate(['/products'], { queryParams: { category: 'electronics' } }); -// Multiple parameters +// Múltiples parámetros // /products?category=electronics&sort=price&page=1 router.navigate(['/products'], { queryParams: { @@ -134,9 +134,9 @@ router.navigate(['/products'], { }); ``` -You can access query parameters with `route.queryParams`. +Puedes acceder a los parámetros de consulta con `route.queryParams`. -Here is an example of a `ProductListComponent` that updates the query parameters that affect how it displays a list of products: +Aquí hay un ejemplo de un `ProductListComponent` que actualiza los parámetros de consulta que afectan cómo muestra una lista de productos: ```angular-ts import { ActivatedRoute, Router } from '@angular/router'; @@ -149,7 +149,7 @@ import { ActivatedRoute, Router } from '@angular/router'; - + ` }) @@ -158,7 +158,7 @@ export class ProductListComponent implements OnInit { private router = inject(Router); constructor() { - // Access query parameters reactively + // Acceder a parámetros de consulta de forma reactiva this.route.queryParams.subscribe(params => { const sort = params['sort'] || 'price'; const page = Number(params['page']) || 1; @@ -168,22 +168,22 @@ export class ProductListComponent implements OnInit { updateSort(event: Event) { const sort = (event.target as HTMLSelectElement).value; - // Update URL with new query parameter + // Actualizar URL con nuevo parámetro de consulta this.router.navigate([], { queryParams: { sort }, - queryParamsHandling: 'merge' // Preserve other query parameters + queryParamsHandling: 'merge' // Preservar otros parámetros de consulta }); } } ``` -In this example, users can use a select element to sort the product list by name or price. The associated change handler updates the URL’s query parameters, which in turn triggers a change event that can read the updated query parameters and update the product list. +En este ejemplo, los usuarios pueden usar un elemento select para ordenar la lista de productos por nombre o precio. El manejador de cambio asociado actualiza los parámetros de consulta de la URL, lo que a su vez desencadena un evento de cambio que puede leer los parámetros de consulta actualizados y actualizar la lista de productos. -For more information, check out the [official docs on QueryParamsHandling](/api/router/QueryParamsHandling). +Para más información, consulta los [docs oficiales sobre QueryParamsHandling](/api/router/QueryParamsHandling). -## Detect active current route with RouterLinkActive +## Detectar ruta activa actual con RouterLinkActive -You can use the `RouterLinkActive` directive to dynamically style navigation elements based on the current active route. This is common in navigation elements to inform users what the active route is. +Puedes usar la directiva `RouterLinkActive` para estilizar dinámicamente elementos de navegación basándose en la ruta activa actual. Esto es común en elementos de navegación para informar a los usuarios cuál es la ruta activa. ```angular-html ``` -In this example, Angular Router will apply the `active-button` class to the correct anchor link and `ariaCurrentWhenActive` to `page` when the URL matches the corresponding `routerLink`. +En este ejemplo, el Router de Angular aplicará la clase `active-button` al enlace anchor correcto y `ariaCurrentWhenActive` a `page` cuando la URL coincida con el `routerLink` correspondiente. -If you need to add multiple classes onto the element, you can use either a space-separated string or an array: +Si necesitas agregar múltiples clases al elemento, puedes usar un string separado por espacios o un array: ```angular-html - + Bob - + Bob ``` -When you specify a value for routerLinkActive, you are also defining the same value for `ariaCurrentWhenActive`. This makes sure that visually impaired users (which may not perceive the different styling being applied) can also identify the active button. +Cuando especificas un valor para routerLinkActive, también estás definiendo el mismo valor para `ariaCurrentWhenActive`. Esto asegura que los usuarios con discapacidad visual (que pueden no percibir el estilo diferente que se está aplicando) también puedan identificar el botón activo. -If you want to define a different value for aria, you’ll need to explicitly set the value using the `ariaCurrentWhenActive` directive. +Si quieres definir un valor diferente para aria, necesitarás establecer explícitamente el valor usando la directiva `ariaCurrentWhenActive`. -### Route matching strategy +### Estrategia de coincidencia de ruta -By default, `RouterLinkActive` considers any ancestors in the route a match. +Por defecto, `RouterLinkActive` considera cualquier ancestro en la ruta como una coincidencia. ```angular-html @@ -231,11 +231,11 @@ By default, `RouterLinkActive` considers any ancestors in the route a match. ``` -When the user visits `/user/jane/role/admin`, both links would have the `active-link` class. +Cuando el usuario visita `/user/jane/role/admin`, ambos enlaces tendrían la clase `active-link`. -### Only apply RouterLinkActive on exact route matches +### Solo aplicar RouterLinkActive en coincidencias exactas de ruta -If you only want to apply the class on an exact match, you need to provide the `routerLinkActiveOptions` directive with a configuration object that contains the value `exact: true`. +Si solo quieres aplicar la clase en una coincidencia exacta, necesitas proporcionar la directiva `routerLinkActiveOptions` con un objeto de configuración que contenga el valor `exact: true`. ```angular-html ``` -If you want to be more precise in how a route is matched, it’s worth noting that `exact: true` is actually syntactic sugar for the full set of matching options: +Si quieres ser más preciso en cómo se hace coincidir una ruta, vale la pena notar que `exact: true` es en realidad azúcar sintáctica para el conjunto completo de opciones de coincidencia: ```angular-ts -// `exact: true` is equivalent to +// `exact: true` es equivalente a { paths: 'exact', fragment: 'ignored', @@ -263,7 +263,7 @@ If you want to be more precise in how a route is matched, it’s worth noting th queryParams: 'exact', } -// `exact: false` is equivalent +// `exact: false` es equivalente { paths: 'subset', fragment: 'ignored', @@ -272,11 +272,11 @@ If you want to be more precise in how a route is matched, it’s worth noting th } ``` -For more information, check out the official docs for [isActiveMatchOptions](/api/router/IsActiveMatchOptions). +Para más información, consulta los docs oficiales para [isActiveMatchOptions](/api/router/IsActiveMatchOptions). -### Apply RouterLinkActive to an ancestor +### Aplicar RouterLinkActive a un ancestro -The RouterLinkActive directive can also be applied to an ancestor element in order to allow developers to style the elements as desired. +La directiva RouterLinkActive también se puede aplicar a un elemento ancestro para permitir a los desarrolladores estilizar los elementos como deseen. ```angular-html
@@ -285,4 +285,4 @@ The RouterLinkActive directive can also be applied to an ancestor element in ord
``` -For more information, check out the [API docs for RouterLinkActive](/api/router/RouterLinkActive). +Para más información, consulta los [docs de la API para RouterLinkActive](/api/router/RouterLinkActive). diff --git a/adev-es/src/content/guide/routing/redirecting-routes.en.md b/adev-es/src/content/guide/routing/redirecting-routes.en.md new file mode 100644 index 0000000..1d3fa96 --- /dev/null +++ b/adev-es/src/content/guide/routing/redirecting-routes.en.md @@ -0,0 +1,144 @@ +# Redirecting Routes + +Route redirects allow you to automatically navigate users from one route to another. Think of it like mail forwarding, where mail intended for one address is sent to a different address. This is useful for handling legacy URLs, implementing default routes, or managing access control. + +## How to configure redirects + +You can define redirects in your route configuration with the `redirectTo` property. This property accepts a string. + +```ts +import { Routes } from '@angular/router'; + +const routes: Routes = [ + // Simple redirect + { path: 'marketing', redirectTo: 'newsletter' }, + + // Redirect with path parameters + { path: 'legacy-user/:id', redirectTo: 'users/:id' }, + + // Redirect any other URLs that don't match + // (also known as a "wildcard" redirect) + { path: '**', redirectTo: '/login' } +]; +``` + +In this example, there are three redirects: + +1. When a user visits the `/marketing` path, they are redirected to `/newsletter`. +2. When a user visits any `/legacy-user/:id` path, they are routed to the corresponding `/users/:id` path. +3. When a user visit any path that's not defined in the router, they are redirected to the login page because of the `**` wildcard path definition. + +## Understanding `pathMatch` + +The `pathMatch` property on routes enables developers to control how Angular matches a URL to routes. + +There are two values that `pathMatch` accepts: + +| Value | Description | +| ---------- | -------------------------------------------- | +| `'full'` | The entire URL path must match exactly | +| `'prefix'` | Only the beginning of the URL needs to match | + +By default, all redirects use the `prefix` strategy. + +### `pathMatch: 'prefix'` + +`pathMatch: 'prefix'` is the default strategy and ideal when you want Angular Router to match all subsequent routes when triggering a redirect. + +```ts +export const routes: Routes = [ + // This redirect route is equivalent to… + { path: 'news', redirectTo: 'blog }, + + // This explicitly defined route redirect pathMatch + { path: 'news', redirectTo: 'blog', pathMatch: 'prefix' }, +]; +``` + +In this example, all routes that are prefixed with `news` are redirected to their `/blog` equivalents. Here are some examples where users are redirected when visiting the old `news` prefix: + +- `/news` redirects to `/blog` +- `/news/article` redirects to `/blog/article` +- `/news/article/:id` redirects to `/blog/article/:id` + +### `pathMatch: 'full'` + +On the other hand, `pathMatch: 'full'` is useful when you want Angular Router to only redirect a specific path. + +```ts +export const routes: Routes = [ + { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, +]; +``` + +In this example, any time the user visits the root URL (i.e., `''`), the router redirects that user to the `'/dashboard'` page. + +Any subsequent pages (e.g., `/login`, `/about`, `/product/id`, etc.), are ignored and do not trigger a redirect. + +TIP: Be careful when configuring a redirect on the root page (i.e., `"/"` or `""`). If you do not set `pathMatch: 'full'`, the router will redirect all URLs. + +To further illustrate this, if the `news` example from the previous section used `pathMatch: 'full'` instead: + +```ts +export const routes: Routes = [ + { path: 'news', redirectTo: '/blog', pathMatch: 'full' }, +]; +``` + +This means that: + +1. Only the `/news` path will be redirected to `/blog`. +2. Any subsequent segments such as `/news/articles` or `/news/articles/1` would not redirect with the new `/blog` prefix. + +## Conditional redirects + +The `redirectTo` property can also accept a function in order to add logic to how users are redirected. + +The [function](api/router/RedirectFunction) only has access part of the [`ActivatedRouteSnapshot`](api/router/ActivatedRouteSnapshot) data since some data is not accurately known at the route matching phase. Examples include: resolved titles, lazy loaded components, etc. + +It typically returns a string or [`URLTree`](api/router/UrlTree), but it can also return an observable or promise. + +Here is an example where the user is redirected to different menu based on the time of the day: + +```ts +import { Routes } from '@angular/router'; +import { MenuComponent } from './menu/menu.component'; + +export const routes: Routes = [ + { + path: 'restaurant/:location/menu', + redirectTo: (activatedRouteSnapshot) => { + const location = activatedRouteSnapshot.params['location']; + const currentHour = new Date().getHours(); + + // Check if user requested a specific meal via query parameter + if (activatedRouteSnapshot.queryParams['meal']) { + return `/restaurant/${location}/menu/${queryParams['meal']}`; + } + + // Auto-redirect based on time of day + if (currentHour >= 5 && currentHour < 11) { + return `/restaurant/${location}/menu/breakfast`; + } else if (currentHour >= 11 && currentHour < 17) { + return `/restaurant/${location}/menu/lunch`; + } else { + return `/restaurant/${location}/menu/dinner`; + } + } + }, + + // Destination routes + { path: 'restaurant/:location/menu/breakfast', component: MenuComponent }, + { path: 'restaurant/:location/menu/lunch', component: MenuComponent }, + { path: 'restaurant/:location/menu/dinner', component: MenuComponent }, + + // Default redirect + { path: '', redirectTo: '/restaurant/downtown/menu', pathMatch: 'full' } +]; +``` + +To learn more, check out [the API docs for the RedirectFunction](api/router/RedirectFunction). + +## Next steps + +For more information about the `redirectTo` property, check out the [API docs](api/router/Route#redirectTo). diff --git a/adev-es/src/content/guide/routing/redirecting-routes.md b/adev-es/src/content/guide/routing/redirecting-routes.md index d8b6148..27b4409 100644 --- a/adev-es/src/content/guide/routing/redirecting-routes.md +++ b/adev-es/src/content/guide/routing/redirecting-routes.md @@ -1,69 +1,69 @@ -# Redirecting Routes +# Redirigiendo rutas -Route redirects allow you to automatically navigate users from one route to another. Think of it like mail forwarding, where mail intended for one address is sent to a different address. This is useful for handling legacy URLs, implementing default routes, or managing access control. +Las redirecciones de rutas te permiten navegar automáticamente a los usuarios de una ruta a otra. Piénsalo como el reenvío de correo, donde el correo destinado a una dirección se envía a una dirección diferente. Esto es útil para manejar URLs heredadas, implementar rutas predeterminadas o gestionar el control de acceso. -## How to configure redirects +## Cómo configurar redirecciones -You can define redirects in your route configuration with the `redirectTo` property. This property accepts a string. +Puedes definir redirecciones en tu configuración de rutas con la propiedad `redirectTo`. Esta propiedad acepta un string. ```ts import { Routes } from '@angular/router'; const routes: Routes = [ - // Simple redirect + // Redirección simple { path: 'marketing', redirectTo: 'newsletter' }, - // Redirect with path parameters + // Redirección con parámetros de ruta { path: 'legacy-user/:id', redirectTo: 'users/:id' }, - // Redirect any other URLs that don’t match - // (also known as a "wildcard" redirect) + // Redirigir cualquier otra URL que no coincida + // (también conocida como redirección "comodín") { path: '**', redirectTo: '/login' } ]; ``` -In this example, there are three redirects: +En este ejemplo, hay tres redirecciones: -1. When a user visits the `/marketing` path, they are redirected to `/newsletter`. -2. When a user visits any `/legacy-user/:id` path, they are routed to the corresponding `/users/:id` path. -3. When a user visit any path that’s not defined in the router, they are redirected to the login page because of the `**` wildcard path definition. +1. Cuando un usuario visita la ruta `/marketing`, es redirigido a `/newsletter`. +2. Cuando un usuario visita cualquier ruta `/legacy-user/:id`, es enrutado a la ruta `/users/:id` correspondiente. +3. Cuando un usuario visita cualquier ruta que no está definida en el router, es redirigido a la página de inicio de sesión debido a la definición de ruta comodín `**`. -## Understanding `pathMatch` +## Entendiendo `pathMatch` -The `pathMatch` property on routes enables developers to control how Angular matches a URL to routes. +La propiedad `pathMatch` en las rutas permite a los desarrolladores controlar cómo Angular hace coincidir una URL con las rutas. -There are two values that `pathMatch` accepts: +Hay dos valores que `pathMatch` acepta: -| Value | Description | -| ---------- | -------------------------------------------- | -| `'full'` | The entire URL path must match exactly | -| `'prefix'` | Only the beginning of the URL needs to match | +| Valor | Descripción | +| ---------- | -------------------------------------------------- | +| `'full'` | La ruta URL completa debe coincidir exactamente | +| `'prefix'` | Solo el comienzo de la URL necesita coincidir | -By default, all redirects use the `prefix` strategy. +Por defecto, todas las redirecciones usan la estrategia `prefix`. ### `pathMatch: 'prefix'` -`pathMatch: 'prefix'` is the default strategy and ideal when you want Angular Router to match all subsequent routes when triggering a redirect. +`pathMatch: 'prefix'` es la estrategia predeterminada e ideal cuando quieres que Angular Router coincida con todas las rutas subsiguientes al disparar una redirección. ```ts export const routes: Routes = [ - // This redirect route is equivalent to… + // Esta ruta de redirección es equivalente a… { path: 'news', redirectTo: 'blog }, - // This explicitly defined route redirect pathMatch + // Esta ruta de redirección define explícitamente pathMatch { path: 'news', redirectTo: 'blog', pathMatch: 'prefix' }, ]; ``` -In this example, all routes that are prefixed with `news` are redirected to their `/blog` equivalents. Here are some examples where users are redirected when visiting the old `news` prefix: +En este ejemplo, todas las rutas que tienen el prefijo `news` son redirigidas a sus equivalentes `/blog`. Aquí hay algunos ejemplos donde los usuarios son redirigidos al visitar el antiguo prefijo `news`: -- `/news` redirects to `/blog` -- `/news/article` redirects to `/blog/article` -- `/news/article/:id` redirects to `/blog/article/:id` +- `/news` redirige a `/blog` +- `/news/article` redirige a `/blog/article` +- `/news/article/:id` redirige a `/blog/article/:id` ### `pathMatch: 'full'` -On the other hand, `pathMatch: 'full'` is useful when you want Angular Router to only redirect a specific path. +Por otro lado, `pathMatch: 'full'` es útil cuando quieres que Angular Router solo redirija una ruta específica. ```ts export const routes: Routes = [ @@ -71,13 +71,13 @@ export const routes: Routes = [ ]; ``` -In this example, any time the user visits the root URL (i.e., `''`), the router redirects that user to the `'/dashboard'` page. +En este ejemplo, cada vez que el usuario visita la URL raíz (es decir, `''`), el router redirige a ese usuario a la página `'/dashboard'`. -Any subsequent pages (e.g., `/login`, `/about`, `/product/id`, etc.), are ignored and do not trigger a redirect. +Cualquier página subsiguiente (por ejemplo, `/login`, `/about`, `/product/id`, etc.), es ignorada y no dispara una redirección. -TIP: Be careful when configuring a redirect on the root page (i.e., `"/"` or `""`). If you do not set `pathMatch: 'full'`, the router will redirect all URLs. +CONSEJO: Ten cuidado al configurar una redirección en la página raíz (es decir, `"/"` o `""`). Si no estableces `pathMatch: 'full'`, el router redirigirá todas las URLs. -To further illustrate this, if the `news` example from the previous section used `pathMatch: 'full'` instead: +Para ilustrar esto aún más, si el ejemplo de `news` de la sección anterior usara `pathMatch: 'full'` en su lugar: ```ts export const routes: Routes = [ @@ -85,20 +85,20 @@ export const routes: Routes = [ ]; ``` -This means that: +Esto significa que: -1. Only the `/news` path will be redirected to `/blog`. -2. Any subsequent segments such as `/news/articles` or `/news/articles/1` would not redirect with the new `/blog` prefix. +1. Solo la ruta `/news` será redirigida a `/blog`. +2. Cualquier segmento subsiguiente como `/news/articles` o `/news/articles/1` no redirigiría con el nuevo prefijo `/blog`. -## Conditional redirects +## Redirecciones condicionales -The `redirectTo` property can also accept a function in order to add logic to how users are redirected. +La propiedad `redirectTo` también puede aceptar una función para agregar lógica a cómo los usuarios son redirigidos. -The [function](api/router/RedirectFunction) only has access part of the [`ActivatedRouteSnapshot`](api/router/ActivatedRouteSnapshot) data since some data is not accurately known at the route matching phase. Examples include: resolved titles, lazy loaded components, etc. +La [función](api/router/RedirectFunction) solo tiene acceso a parte de los datos de [`ActivatedRouteSnapshot`](api/router/ActivatedRouteSnapshot) ya que algunos datos no se conocen con precisión en la fase de coincidencia de rutas. Los ejemplos incluyen: títulos resueltos, componentes cargados de forma diferida, etc. -It typically returns a string or [`URLTree`](api/router/UrlTree), but it can also return an observable or promise. +Típicamente retorna un string o [`URLTree`](api/router/UrlTree), pero también puede retornar un observable o promesa. -Here is an example where the user is redirected to different menu based on the time of the day: +Aquí hay un ejemplo donde el usuario es redirigido a diferentes menús según la hora del día: ```ts import { Routes } from '@angular/router'; @@ -111,12 +111,12 @@ export const routes: Routes = [ const location = activatedRouteSnapshot.params['location']; const currentHour = new Date().getHours(); - // Check if user requested a specific meal via query parameter + // Verificar si el usuario solicitó una comida específica mediante parámetro de consulta if (activatedRouteSnapshot.queryParams['meal']) { return `/restaurant/${location}/menu/${queryParams['meal']}`; } - // Auto-redirect based on time of day + // Redirección automática según la hora del día if (currentHour >= 5 && currentHour < 11) { return `/restaurant/${location}/menu/breakfast`; } else if (currentHour >= 11 && currentHour < 17) { @@ -127,18 +127,18 @@ export const routes: Routes = [ } }, - // Destination routes + // Rutas de destino { path: 'restaurant/:location/menu/breakfast', component: MenuComponent }, { path: 'restaurant/:location/menu/lunch', component: MenuComponent }, { path: 'restaurant/:location/menu/dinner', component: MenuComponent }, - // Default redirect + // Redirección predeterminada { path: '', redirectTo: '/restaurant/downtown/menu', pathMatch: 'full' } ]; ``` -To learn more, check out [the API docs for the RedirectFunction](api/router/RedirectFunction). +Para aprender más, consulta [la documentación de la API para RedirectFunction](api/router/RedirectFunction). -## Next steps +## Próximos pasos -For more information about the `redirectTo` property, check out the [API docs](api/router/Route#redirectTo). +Para más información sobre la propiedad `redirectTo`, consulta la [documentación de la API](api/router/Route#redirectTo). diff --git a/adev-es/src/content/guide/routing/rendering-strategies.en.md b/adev-es/src/content/guide/routing/rendering-strategies.en.md new file mode 100644 index 0000000..621968d --- /dev/null +++ b/adev-es/src/content/guide/routing/rendering-strategies.en.md @@ -0,0 +1,139 @@ +# Rendering strategies in Angular + +This guide helps you choose the right rendering strategy for different parts of your Angular application. + +## What are rendering strategies? + +Rendering strategies determine when and where your Angular application's HTML content is generated. Each strategy offers different trade-offs between initial page load performance, interactivity, SEO capabilities, and server resource usage. + +Angular supports three primary rendering strategies: + +- **Client-Side Rendering (CSR)** - Content is rendered entirely in the browser +- **Static Site Generation (SSG/Prerendering)** - Content is pre-rendered at build time +- **Server-Side Rendering (SSR)** - Content is rendered on the server for the initial request for a route + +## Client-Side Rendering (CSR) + +**CSR is Angular's default.** Content renders entirely in the browser after JavaScript loads. + +### When to use CSR + +✅ It can be a good fit for: + +- Interactive applications (dashboards, admin panels) +- Real-time applications +- Internal tools where SEO doesn't matter +- Single-page applications with complex client-side state + +❌ When possible, consider avoiding it for: + +- Public-facing content that needs SEO +- Pages where initial load performance is critical + +### CSR trade-offs + +| Aspect | Impact | +| :---------------- | :------------------------------------------------------- | +| **SEO** | Poor - content not visible to crawlers until JS executes | +| **Initial load** | Slower - must download and execute JavaScript first | +| **Interactivity** | Immediate once loaded | +| **Server needs** | Minimal outside of some configuration | +| **Complexity** | Simplest because it works with minimum configuration | + +## Static Site Generation (SSG/Prerendering) + +**SSG pre-renders pages at build time** into static HTML files. The server sends pre-built HTML for the initial page load. After hydration, your app runs entirely in the browser like a traditional SPA - subsequent navigation, route changes, and API calls all happen client-side without server rendering. + +### When to use SSG + +✅ It can be a good fit for: + +- Marketing pages and landing pages +- Blog posts and documentation +- Product catalogs with stable content +- Content that doesn't change per-user + +❌ When possible, consider avoiding it for: + +- User-specific content +- Frequently changing data +- Real-time information + +### SSG trade-offs + +| Aspect | Impact | +| :------------------ | :------------------------------------------ | +| **SEO** | Excellent - full HTML available immediately | +| **Initial load** | Fastest - pre-generated HTML | +| **Interactivity** | After hydration completes | +| **Server needs** | None for serving (CDN-friendly) | +| **Build time** | Longer - generates all pages upfront | +| **Content updates** | Requires rebuild and redeploy | + +📖 **Implementation:** See [Customizing build-time prerendering](guide/ssr#customizing-build-time-prerendering-ssg) in the SSR guide. + +## Server-Side Rendering (SSR) + +**SSR generates HTML on the server for the initial request for a route**, providing dynamic content with good SEO. The server renders HTML and sends it to the client. + +Once the client renders the page, Angular [hydrates](/guide/hydration#what-is-hydration) the app and it then runs entirely in the browser like a traditional SPA - subsequent navigation, route changes, and API calls all happen client-side without additional server rendering. + +### When to use SSR + +✅ It can be a good fit for: + +- E-commerce product pages (dynamic pricing/inventory) +- News sites and social media feeds +- Personalized content that changes frequently + +❌ When possible, consider avoiding it for: + +- Static content (use SSG instead) +- When server costs are a concern + +### SSR trade-offs + +| Aspect | Impact | +| :------------------ | :-------------------------------------------------- | +| **SEO** | Excellent - full HTML for crawlers | +| **Initial load** | Fast - immediate content visibility | +| **Interactivity** | Delayed until hydration | +| **Server needs** | Requires server | +| **Personalization** | Full access to user context | +| **Server costs** | Higher - renders on the initial request for a route | + +📖 **Implementation:** See [Server routing](guide/ssr#server-routing) and [Authoring server-compatible components](guide/ssr#authoring-server-compatible-components) in the SSR guide. + +## Choosing the Right Strategy + +### Decision matrix + +| If you need... | Use this strategy | Why | +| :------------------------- | :---------------- | :----------------------------------------------- | +| **SEO + Static content** | SSG | Pre-rendered HTML, fastest load | +| **SEO + Dynamic content** | SSR | Fresh content on the initial request for a route | +| **No SEO + Interactivity** | CSR | Simplest, no server needed | +| **Mixed requirements** | Hybrid | Different strategies per route | + +## Making SSR/SSG Interactive with Hydration + +When using SSR or SSG, Angular "hydrates" the server-rendered HTML to make it interactive. + +**Available strategies:** + +- **Full hydration** - Entire app becomes interactive at once (default) +- **Incremental hydration** - Parts become interactive as needed (better performance) +- **Event replay** - Captures clicks before hydration completes + +📖 **Learn more:** + +- [Hydration guide](guide/hydration) - Complete hydration setup +- [Incremental hydration](guide/incremental-hydration) - Advanced hydration with `@defer` blocks + +## Next steps + + + + + + diff --git a/adev-es/src/content/guide/routing/rendering-strategies.md b/adev-es/src/content/guide/routing/rendering-strategies.md index 621968d..c9bfe29 100644 --- a/adev-es/src/content/guide/routing/rendering-strategies.md +++ b/adev-es/src/content/guide/routing/rendering-strategies.md @@ -1,136 +1,136 @@ -# Rendering strategies in Angular +# Estrategias de renderización en Angular -This guide helps you choose the right rendering strategy for different parts of your Angular application. +Esta guía te ayuda a elegir la estrategia de renderización correcta para diferentes partes de tu aplicación Angular. -## What are rendering strategies? +## ¿Qué son las estrategias de renderización? -Rendering strategies determine when and where your Angular application's HTML content is generated. Each strategy offers different trade-offs between initial page load performance, interactivity, SEO capabilities, and server resource usage. +Las estrategias de renderización determinan cuándo y dónde se genera el contenido HTML de tu aplicación Angular. Cada estrategia ofrece diferentes compensaciones entre rendimiento de carga inicial de página, interactividad, capacidades de SEO y uso de recursos del servidor. -Angular supports three primary rendering strategies: +Angular soporta tres estrategias de renderización principales: -- **Client-Side Rendering (CSR)** - Content is rendered entirely in the browser -- **Static Site Generation (SSG/Prerendering)** - Content is pre-rendered at build time -- **Server-Side Rendering (SSR)** - Content is rendered on the server for the initial request for a route +- **Client-Side Rendering (CSR)** - El contenido se renderiza completamente en el navegador +- **Static Site Generation (SSG/Prerendering)** - El contenido se pre-renderiza en tiempo de compilación +- **Server-Side Rendering (SSR)** - El contenido se renderiza en el servidor para la solicitud inicial de una ruta ## Client-Side Rendering (CSR) -**CSR is Angular's default.** Content renders entirely in the browser after JavaScript loads. +**CSR es el valor predeterminado de Angular.** El contenido se renderiza completamente en el navegador después de que JavaScript se carga. -### When to use CSR +### Cuándo usar CSR -✅ It can be a good fit for: +✅ Puede ser una buena opción para: -- Interactive applications (dashboards, admin panels) -- Real-time applications -- Internal tools where SEO doesn't matter -- Single-page applications with complex client-side state +- Aplicaciones interactivas (dashboards, paneles de administración) +- Aplicaciones en tiempo real +- Herramientas internas donde el SEO no importa +- Aplicaciones de página única con estado complejo del lado del cliente -❌ When possible, consider avoiding it for: +❌ Cuando sea posible, considera evitarlo para: -- Public-facing content that needs SEO -- Pages where initial load performance is critical +- Contenido público que necesita SEO +- Páginas donde el rendimiento de carga inicial es crítico -### CSR trade-offs +### Compensaciones de CSR -| Aspect | Impact | +| Aspecto | Impacto | | :---------------- | :------------------------------------------------------- | -| **SEO** | Poor - content not visible to crawlers until JS executes | -| **Initial load** | Slower - must download and execute JavaScript first | -| **Interactivity** | Immediate once loaded | -| **Server needs** | Minimal outside of some configuration | -| **Complexity** | Simplest because it works with minimum configuration | +| **SEO** | Pobre - contenido no visible para crawlers hasta que JS se ejecuta | +| **Carga inicial** | Más lenta - debe descargar y ejecutar JavaScript primero | +| **Interactividad** | Inmediata una vez cargada | +| **Necesidades del servidor** | Mínimas fuera de alguna configuración | +| **Complejidad** | Más simple porque funciona con configuración mínima | ## Static Site Generation (SSG/Prerendering) -**SSG pre-renders pages at build time** into static HTML files. The server sends pre-built HTML for the initial page load. After hydration, your app runs entirely in the browser like a traditional SPA - subsequent navigation, route changes, and API calls all happen client-side without server rendering. +**SSG pre-renderiza páginas en tiempo de compilación** en archivos HTML estáticos. El servidor envía HTML pre-construido para la carga inicial de la página. Después de la hidratación, tu aplicación se ejecuta completamente en el navegador como una SPA tradicional - la navegación subsiguiente, cambios de ruta y llamadas a API ocurren del lado del cliente sin renderización del servidor. -### When to use SSG +### Cuándo usar SSG -✅ It can be a good fit for: +✅ Puede ser una buena opción para: -- Marketing pages and landing pages -- Blog posts and documentation -- Product catalogs with stable content -- Content that doesn't change per-user +- Páginas de marketing y landing pages +- Posts de blog y documentación +- Catálogos de productos con contenido estable +- Contenido que no cambia por usuario -❌ When possible, consider avoiding it for: +❌ Cuando sea posible, considera evitarlo para: -- User-specific content -- Frequently changing data -- Real-time information +- Contenido específico del usuario +- Datos que cambian frecuentemente +- Información en tiempo real -### SSG trade-offs +### Compensaciones de SSG -| Aspect | Impact | +| Aspecto | Impacto | | :------------------ | :------------------------------------------ | -| **SEO** | Excellent - full HTML available immediately | -| **Initial load** | Fastest - pre-generated HTML | -| **Interactivity** | After hydration completes | -| **Server needs** | None for serving (CDN-friendly) | -| **Build time** | Longer - generates all pages upfront | -| **Content updates** | Requires rebuild and redeploy | +| **SEO** | Excelente - HTML completo disponible inmediatamente | +| **Carga inicial** | Más rápida - HTML pre-generado | +| **Interactividad** | Después de que se completa la hidratación | +| **Necesidades del servidor** | Ninguna para servir (compatible con CDN) | +| **Tiempo de compilación** | Más largo - genera todas las páginas por adelantado | +| **Actualizaciones de contenido** | Requiere reconstrucción y redespliegue | -📖 **Implementation:** See [Customizing build-time prerendering](guide/ssr#customizing-build-time-prerendering-ssg) in the SSR guide. +📖 **Implementación:** Consulta [Personalizar prerendering en tiempo de compilación](guide/ssr#customizing-build-time-prerendering-ssg) en la guía de SSR. ## Server-Side Rendering (SSR) -**SSR generates HTML on the server for the initial request for a route**, providing dynamic content with good SEO. The server renders HTML and sends it to the client. +**SSR genera HTML en el servidor para la solicitud inicial de una ruta**, proporcionando contenido dinámico con buen SEO. El servidor renderiza HTML y lo envía al cliente. -Once the client renders the page, Angular [hydrates](/guide/hydration#what-is-hydration) the app and it then runs entirely in the browser like a traditional SPA - subsequent navigation, route changes, and API calls all happen client-side without additional server rendering. +Una vez que el cliente renderiza la página, Angular [hidrata](/guide/hydration#what-is-hydration) la aplicación y luego se ejecuta completamente en el navegador como una SPA tradicional - la navegación subsiguiente, cambios de ruta y llamadas a API ocurren del lado del cliente sin renderización adicional del servidor. -### When to use SSR +### Cuándo usar SSR -✅ It can be a good fit for: +✅ Puede ser una buena opción para: -- E-commerce product pages (dynamic pricing/inventory) -- News sites and social media feeds -- Personalized content that changes frequently +- Páginas de productos de e-commerce (precios/inventario dinámicos) +- Sitios de noticias y feeds de redes sociales +- Contenido personalizado que cambia frecuentemente -❌ When possible, consider avoiding it for: +❌ Cuando sea posible, considera evitarlo para: -- Static content (use SSG instead) -- When server costs are a concern +- Contenido estático (usa SSG en su lugar) +- Cuando los costos del servidor son una preocupación -### SSR trade-offs +### Compensaciones de SSR -| Aspect | Impact | +| Aspecto | Impacto | | :------------------ | :-------------------------------------------------- | -| **SEO** | Excellent - full HTML for crawlers | -| **Initial load** | Fast - immediate content visibility | -| **Interactivity** | Delayed until hydration | -| **Server needs** | Requires server | -| **Personalization** | Full access to user context | -| **Server costs** | Higher - renders on the initial request for a route | +| **SEO** | Excelente - HTML completo para crawlers | +| **Carga inicial** | Rápida - visibilidad de contenido inmediata | +| **Interactividad** | Retrasada hasta la hidratación | +| **Necesidades del servidor** | Requiere servidor | +| **Personalización** | Acceso completo al contexto del usuario | +| **Costos del servidor** | Más altos - renderiza en la solicitud inicial de una ruta | -📖 **Implementation:** See [Server routing](guide/ssr#server-routing) and [Authoring server-compatible components](guide/ssr#authoring-server-compatible-components) in the SSR guide. +📖 **Implementación:** Consulta [Enrutamiento del servidor](guide/ssr#server-routing) y [Crear componentes compatibles con el servidor](guide/ssr#authoring-server-compatible-components) en la guía de SSR. -## Choosing the Right Strategy +## Elegir la estrategia correcta -### Decision matrix +### Matriz de decisión -| If you need... | Use this strategy | Why | +| Si necesitas... | Usa esta estrategia | Por qué | | :------------------------- | :---------------- | :----------------------------------------------- | -| **SEO + Static content** | SSG | Pre-rendered HTML, fastest load | -| **SEO + Dynamic content** | SSR | Fresh content on the initial request for a route | -| **No SEO + Interactivity** | CSR | Simplest, no server needed | -| **Mixed requirements** | Hybrid | Different strategies per route | +| **SEO + Contenido estático** | SSG | HTML pre-renderizado, carga más rápida | +| **SEO + Contenido dinámico** | SSR | Contenido fresco en la solicitud inicial de una ruta | +| **Sin SEO + Interactividad** | CSR | Más simple, sin servidor necesario | +| **Requisitos mixtos** | Híbrido | Diferentes estrategias por ruta | -## Making SSR/SSG Interactive with Hydration +## Hacer SSR/SSG interactivo con hidratación -When using SSR or SSG, Angular "hydrates" the server-rendered HTML to make it interactive. +Cuando usas SSR o SSG, Angular "hidrata" el HTML renderizado del servidor para hacerlo interactivo. -**Available strategies:** +**Estrategias disponibles:** -- **Full hydration** - Entire app becomes interactive at once (default) -- **Incremental hydration** - Parts become interactive as needed (better performance) -- **Event replay** - Captures clicks before hydration completes +- **Hidratación completa** - Toda la aplicación se vuelve interactiva de una vez (predeterminado) +- **Hidratación incremental** - Las partes se vuelven interactivas según sea necesario (mejor rendimiento) +- **Repetición de eventos** - Captura clics antes de que se complete la hidratación -📖 **Learn more:** +📖 **Aprende más:** -- [Hydration guide](guide/hydration) - Complete hydration setup -- [Incremental hydration](guide/incremental-hydration) - Advanced hydration with `@defer` blocks +- [Guía de hidratación](guide/hydration) - Configuración completa de hidratación +- [Hidratación incremental](guide/incremental-hydration) - Hidratación avanzada con bloques `@defer` -## Next steps +## Próximos pasos diff --git a/adev-es/src/content/guide/routing/route-guards.en.md b/adev-es/src/content/guide/routing/route-guards.en.md new file mode 100644 index 0000000..b25e9eb --- /dev/null +++ b/adev-es/src/content/guide/routing/route-guards.en.md @@ -0,0 +1,208 @@ +# Control route access with guards + +CRITICAL: Never rely on client-side guards as the sole source of access control. All JavaScript that runs in a web browser can be modified by the user running the browser. Always enforce user authorization server-side, in addition to any client-side guards. + +Route guards are functions that control whether a user can navigate to or leave a particular route. They are like checkpoints that manage whether a user can access specific routes. Common examples of using route guards include authentication and access control. + +## Creating a route guard + +You can generate a route guard using the Angular CLI: + +```bash +ng generate guard CUSTOM_NAME +``` + +This will prompt you to select which [type of route guard](#types-of-route-guards) to use and then create the corresponding `CUSTOM_NAME-guard.ts` file. + +TIP: You can also create a route guard manually by creating a separate TypeScript file in your Angular project. Developers typically add a suffix of `-guard.ts` in the filename to distinguish it from other files. + +## Route guard return types + +All route guards share the same possible return types. This gives you flexibility in how you control navigation: + +| Return types | Description | +| ------------------------------- | --------------------------------------------------------------------------------- | +| `boolean` | `true` allows navigation, `false` blocks it (see note for `CanMatch` route guard) | +| `UrlTree` or `RedirectCommand` | Redirects to another route instead of blocking | +| `Promise` or `Observable` | Router uses the first emitted value and then unsubscribes | + +Note: `CanMatch` behaves differently— when it returns `false`, Angular tries other matching routes instead of completely blocking navigation. + +## Types of route guards + +Angular provides four types of route guards, each serving different purposes: + + + + + + + + +### CanActivate + +The `CanActivate` guard determines whether a user can access a route. It is most commonly used for authentication and authorization. + +It has access to the following default arguments: + +- `route: ActivatedRouteSnapshot` - Contains information about the route being activated +- `state: RouterStateSnapshot` - Contains the router's current state + +It can return the [standard return guard types](#route-guard-return-types). + +```ts +export const authGuard: CanActivateFn = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { + const authService = inject(AuthService); + return authService.isAuthenticated(); +}; +``` + +Tip: If you need to redirect the user, return a [`URLTree`](api/router/UrlTree) or [`RedirectCommand`](api/router/RedirectCommand). Do **not** return `false` and then programmatically `navigate` the user. + +For more information, check out the [API docs for CanActivateFn](api/router/CanActivateFn). + +### CanActivateChild + +The `CanActivateChild` guard determines whether a user can access child routes of a particular parent route. This is useful when you want to protect an entire section of nested routes. In other words, `canActivateChild` runs for _all_ children. If there is a child component with another child component underneath of it, `canActivateChild` will run once for both components. + +It has access to the following default arguments: + +- `childRoute: ActivatedRouteSnapshot` - Contains information about the "future" snapshot (i.e., state the router is attempting to navigate to) of the child route being activated +- `state: RouterStateSnapshot` - Contains the router's current state + +It can return the [standard return guard types](#route-guard-return-types). + +```ts +export const adminChildGuard: CanActivateChildFn = (childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { + const authService = inject(AuthService); + return authService.hasRole('admin'); +}; +``` + +For more information, check out the [API docs for CanActivateChildFn](api/router/CanActivateChildFn). + +### CanDeactivate + +The `CanDeactivate` guard determines whether a user can leave a route. A common scenario is preventing navigation away from unsaved forms. + +It has access to the following default arguments: + +- `component: T` - The component instance being deactivated +- `currentRoute: ActivatedRouteSnapshot` - Contains information about the current route +- `currentState: RouterStateSnapshot` - Contains the current router state +- `nextState: RouterStateSnapshot` - Contains the next router state being navigated to + +It can return the [standard return guard types](#route-guard-return-types). + +```ts +export const unsavedChangesGuard: CanDeactivateFn = (component: FormComponent, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState: RouterStateSnapshot) => { + return component.hasUnsavedChanges() + ? confirm('You have unsaved changes. Are you sure you want to leave?') + : true; +}; +``` + +For more information, check out the [API docs for CanDeactivateFn](api/router/CanDeactivateFn). + +### CanMatch + +The `CanMatch` guard determines whether a route can be matched during path matching. Unlike other guards, rejection falls through to try other matching routes instead of blocking navigation entirely. This can be useful for feature flags, A/B testing, or conditional route loading. + +It has access to the following default arguments: + +- `route: Route` - The route configuration being evaluated +- `segments: UrlSegment[]` - The URL segments that have not been consumed by previous parent route evaluations + +It can return the [standard return guard types](#route-guard-return-types), but when it returns `false`, Angular tries other matching routes instead of completely blocking navigation. + +```ts +export const featureToggleGuard: CanMatchFn = (route: Route, segments: UrlSegment[]) => { + const featureService = inject(FeatureService); + return featureService.isFeatureEnabled('newDashboard'); +}; +``` + +It can also allow you to use different components for the same path. + +```ts +// 📄 routes.ts +const routes: Routes = [ + { + path: 'dashboard', + component: AdminDashboard, + canMatch: [adminGuard] + }, + { + path: 'dashboard', + component: UserDashboard, + canMatch: [userGuard] + } +] +``` + +In this example, when the user visits `/dashboard`, the first one that matches the correct guard will be used. + +For more information, check out the [API docs for CanMatchFn](api/router/CanMatchFn). + +## Applying guards to routes + +Once you've created your route guards, you need to configure them in your route definitions. + +Guards are specified as arrays in the route configuration in order to allow you to apply multiple guards to a single route. They are executed in the order they appear in the array. + +```ts +import { Routes } from '@angular/router'; +import { authGuard } from './guards/auth.guard'; +import { adminGuard } from './guards/admin.guard'; +import { canDeactivateGuard } from './guards/can-deactivate.guard'; +import { featureToggleGuard } from './guards/feature-toggle.guard'; + +const routes: Routes = [ + // Basic CanActivate - requires authentication + { + path: 'dashboard', + component: DashboardComponent, + canActivate: [authGuard] + }, + + // Multiple CanActivate guards - requires authentication AND admin role + { + path: 'admin', + component: AdminComponent, + canActivate: [authGuard, adminGuard] + }, + + // CanActivate + CanDeactivate - protected route with unsaved changes check + { + path: 'profile', + component: ProfileComponent, + canActivate: [authGuard], + canDeactivate: [canDeactivateGuard] + }, + + // CanActivateChild - protects all child routes + { + path: 'users', // /user - NOT protected + canActivateChild: [authGuard], + children: [ + // /users/list - PROTECTED + { path: 'list', component: UserListComponent }, + // /useres/detail/:id - PROTECTED + { path: 'detail/:id', component: UserDetailComponent } + ] + }, + + // CanMatch - conditionally matches route based on feature flag + { + path: 'beta-feature', + component: BetaFeatureComponent, + canMatch: [featureToggleGuard] + }, + + // Fallback route if beta feature is disabled + { + path: 'beta-feature', + component: ComingSoonComponent + } +]; +``` diff --git a/adev-es/src/content/guide/routing/route-guards.md b/adev-es/src/content/guide/routing/route-guards.md index b25e9eb..8f010f4 100644 --- a/adev-es/src/content/guide/routing/route-guards.md +++ b/adev-es/src/content/guide/routing/route-guards.md @@ -1,36 +1,36 @@ -# Control route access with guards +# Controlar el acceso a rutas con guards -CRITICAL: Never rely on client-side guards as the sole source of access control. All JavaScript that runs in a web browser can be modified by the user running the browser. Always enforce user authorization server-side, in addition to any client-side guards. +CRÍTICO: Nunca confíes en guards del lado del cliente como única fuente de control de acceso. Todo JavaScript que se ejecuta en un navegador web puede ser modificado por el usuario que ejecuta el navegador. Siempre aplica la autorización de usuario del lado del servidor, además de cualquier guard del lado del cliente. -Route guards are functions that control whether a user can navigate to or leave a particular route. They are like checkpoints that manage whether a user can access specific routes. Common examples of using route guards include authentication and access control. +Los guards de ruta son funciones que controlan si un usuario puede navegar hacia o desde una ruta en particular. Son como puntos de control que gestionan si un usuario puede acceder a rutas específicas. Ejemplos comunes de uso de guards de ruta incluyen autenticación y control de acceso. -## Creating a route guard +## Crear un guard de ruta -You can generate a route guard using the Angular CLI: +Puedes generar un guard de ruta usando Angular CLI: ```bash ng generate guard CUSTOM_NAME ``` -This will prompt you to select which [type of route guard](#types-of-route-guards) to use and then create the corresponding `CUSTOM_NAME-guard.ts` file. +Esto te solicitará que selecciones qué [tipo de guard de ruta](#types-of-route-guards) usar y luego creará el archivo `CUSTOM_NAME-guard.ts` correspondiente. -TIP: You can also create a route guard manually by creating a separate TypeScript file in your Angular project. Developers typically add a suffix of `-guard.ts` in the filename to distinguish it from other files. +CONSEJO: También puedes crear un guard de ruta manualmente creando un archivo TypeScript separado en tu proyecto Angular. Los desarrolladores típicamente agregan un sufijo de `-guard.ts` en el nombre del archivo para distinguirlo de otros archivos. -## Route guard return types +## Tipos de retorno de guards de ruta -All route guards share the same possible return types. This gives you flexibility in how you control navigation: +Todos los guards de ruta comparten los mismos tipos de retorno posibles. Esto te da flexibilidad en cómo controlas la navegación: -| Return types | Description | -| ------------------------------- | --------------------------------------------------------------------------------- | -| `boolean` | `true` allows navigation, `false` blocks it (see note for `CanMatch` route guard) | -| `UrlTree` or `RedirectCommand` | Redirects to another route instead of blocking | -| `Promise` or `Observable` | Router uses the first emitted value and then unsubscribes | +| Tipos de retorno | Descripción | +| ------------------------------- | ------------------------------------------------------------------------------------------------ | +| `boolean` | `true` permite la navegación, `false` la bloquea (ver nota para el guard de ruta `CanMatch`) | +| `UrlTree` o `RedirectCommand` | Redirige a otra ruta en lugar de bloquear | +| `Promise` o `Observable` | El router usa el primer valor emitido y luego se desuscribe | -Note: `CanMatch` behaves differently— when it returns `false`, Angular tries other matching routes instead of completely blocking navigation. +Nota: `CanMatch` se comporta de manera diferente— cuando retorna `false`, Angular intenta otras rutas coincidentes en lugar de bloquear completamente la navegación. -## Types of route guards +## Tipos de guards de ruta -Angular provides four types of route guards, each serving different purposes: +Angular proporciona cuatro tipos de guards de ruta, cada uno sirviendo diferentes propósitos: @@ -41,14 +41,14 @@ Angular provides four types of route guards, each serving different purposes: ### CanActivate -The `CanActivate` guard determines whether a user can access a route. It is most commonly used for authentication and authorization. +El guard `CanActivate` determina si un usuario puede acceder a una ruta. Se usa más comúnmente para autenticación y autorización. -It has access to the following default arguments: +Tiene acceso a los siguientes argumentos predeterminados: -- `route: ActivatedRouteSnapshot` - Contains information about the route being activated -- `state: RouterStateSnapshot` - Contains the router's current state +- `route: ActivatedRouteSnapshot` - Contiene información sobre la ruta que está siendo activada +- `state: RouterStateSnapshot` - Contiene el estado actual del router -It can return the [standard return guard types](#route-guard-return-types). +Puede retornar los [tipos de retorno estándar de guards](#tipos-de-retorno-de-guards-de-ruta). ```ts export const authGuard: CanActivateFn = (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { @@ -57,20 +57,20 @@ export const authGuard: CanActivateFn = (route: ActivatedRouteSnapshot, state: R }; ``` -Tip: If you need to redirect the user, return a [`URLTree`](api/router/UrlTree) or [`RedirectCommand`](api/router/RedirectCommand). Do **not** return `false` and then programmatically `navigate` the user. +Consejo: Si necesitas redirigir al usuario, retorna un [`URLTree`](api/router/UrlTree) o [`RedirectCommand`](api/router/RedirectCommand). **No** retornes `false` y luego navegues al usuario programáticamente. -For more information, check out the [API docs for CanActivateFn](api/router/CanActivateFn). +Para más información, consulta la [documentación de la API para CanActivateFn](api/router/CanActivateFn). ### CanActivateChild -The `CanActivateChild` guard determines whether a user can access child routes of a particular parent route. This is useful when you want to protect an entire section of nested routes. In other words, `canActivateChild` runs for _all_ children. If there is a child component with another child component underneath of it, `canActivateChild` will run once for both components. +El guard `CanActivateChild` determina si un usuario puede acceder a rutas hijas de una ruta padre en particular. Esto es útil cuando quieres proteger una sección completa de rutas anidadas. En otras palabras, `canActivateChild` se ejecuta para _todos_ los hijos. Si hay un componente hijo con otro componente hijo debajo de él, `canActivateChild` se ejecutará una vez para ambos componentes. -It has access to the following default arguments: +Tiene acceso a los siguientes argumentos predeterminados: -- `childRoute: ActivatedRouteSnapshot` - Contains information about the "future" snapshot (i.e., state the router is attempting to navigate to) of the child route being activated -- `state: RouterStateSnapshot` - Contains the router's current state +- `childRoute: ActivatedRouteSnapshot` - Contiene información sobre la snapshot "futura" (es decir, el estado al que el router está intentando navegar) de la ruta hija que está siendo activada +- `state: RouterStateSnapshot` - Contiene el estado actual del router -It can return the [standard return guard types](#route-guard-return-types). +Puede retornar los [tipos de retorno estándar de guards](#tipos-de-retorno-de-guards-de-ruta). ```ts export const adminChildGuard: CanActivateChildFn = (childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { @@ -79,41 +79,41 @@ export const adminChildGuard: CanActivateChildFn = (childRoute: ActivatedRouteSn }; ``` -For more information, check out the [API docs for CanActivateChildFn](api/router/CanActivateChildFn). +Para más información, consulta la [documentación de la API para CanActivateChildFn](api/router/CanActivateChildFn). ### CanDeactivate -The `CanDeactivate` guard determines whether a user can leave a route. A common scenario is preventing navigation away from unsaved forms. +El guard `CanDeactivate` determina si un usuario puede salir de una ruta. Un escenario común es prevenir la navegación desde formularios no guardados. -It has access to the following default arguments: +Tiene acceso a los siguientes argumentos predeterminados: -- `component: T` - The component instance being deactivated -- `currentRoute: ActivatedRouteSnapshot` - Contains information about the current route -- `currentState: RouterStateSnapshot` - Contains the current router state -- `nextState: RouterStateSnapshot` - Contains the next router state being navigated to +- `component: T` - La instancia del componente que está siendo desactivada +- `currentRoute: ActivatedRouteSnapshot` - Contiene información sobre la ruta actual +- `currentState: RouterStateSnapshot` - Contiene el estado actual del router +- `nextState: RouterStateSnapshot` - Contiene el siguiente estado del router al que se está navegando -It can return the [standard return guard types](#route-guard-return-types). +Puede retornar los [tipos de retorno estándar de guards](#tipos-de-retorno-de-guards-de-ruta). ```ts export const unsavedChangesGuard: CanDeactivateFn = (component: FormComponent, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState: RouterStateSnapshot) => { return component.hasUnsavedChanges() - ? confirm('You have unsaved changes. Are you sure you want to leave?') + ? confirm('Tienes cambios sin guardar. ¿Estás seguro de que quieres salir?') : true; }; ``` -For more information, check out the [API docs for CanDeactivateFn](api/router/CanDeactivateFn). +Para más información, consulta la [documentación de la API para CanDeactivateFn](api/router/CanDeactivateFn). ### CanMatch -The `CanMatch` guard determines whether a route can be matched during path matching. Unlike other guards, rejection falls through to try other matching routes instead of blocking navigation entirely. This can be useful for feature flags, A/B testing, or conditional route loading. +El guard `CanMatch` determina si una ruta puede ser coincidente durante la coincidencia de rutas. A diferencia de otros guards, el rechazo recurre a intentar otras rutas coincidentes en lugar de bloquear la navegación por completo. Esto puede ser útil para feature flags, pruebas A/B o carga condicional de rutas. -It has access to the following default arguments: +Tiene acceso a los siguientes argumentos predeterminados: -- `route: Route` - The route configuration being evaluated -- `segments: UrlSegment[]` - The URL segments that have not been consumed by previous parent route evaluations +- `route: Route` - La configuración de ruta que está siendo evaluada +- `segments: UrlSegment[]` - Los segmentos URL que no han sido consumidos por evaluaciones de rutas padre previas -It can return the [standard return guard types](#route-guard-return-types), but when it returns `false`, Angular tries other matching routes instead of completely blocking navigation. +Puede retornar los [tipos de retorno estándar de guards](#tipos-de-retorno-de-guards-de-ruta), pero cuando retorna `false`, Angular intenta otras rutas coincidentes en lugar de bloquear completamente la navegación. ```ts export const featureToggleGuard: CanMatchFn = (route: Route, segments: UrlSegment[]) => { @@ -122,7 +122,7 @@ export const featureToggleGuard: CanMatchFn = (route: Route, segments: UrlSegmen }; ``` -It can also allow you to use different components for the same path. +También puede permitirte usar diferentes componentes para la misma ruta. ```ts // 📄 routes.ts @@ -140,15 +140,15 @@ const routes: Routes = [ ] ``` -In this example, when the user visits `/dashboard`, the first one that matches the correct guard will be used. +En este ejemplo, cuando el usuario visita `/dashboard`, se usará el primero que coincida con el guard correcto. -For more information, check out the [API docs for CanMatchFn](api/router/CanMatchFn). +Para más información, consulta la [documentación de la API para CanMatchFn](api/router/CanMatchFn). -## Applying guards to routes +## Aplicar guards a rutas -Once you've created your route guards, you need to configure them in your route definitions. +Una vez que hayas creado tus guards de ruta, necesitas configurarlos en tus definiciones de rutas. -Guards are specified as arrays in the route configuration in order to allow you to apply multiple guards to a single route. They are executed in the order they appear in the array. +Los guards se especifican como arrays en la configuración de ruta para permitirte aplicar múltiples guards a una sola ruta. Se ejecutan en el orden en que aparecen en el array. ```ts import { Routes } from '@angular/router'; @@ -158,21 +158,21 @@ import { canDeactivateGuard } from './guards/can-deactivate.guard'; import { featureToggleGuard } from './guards/feature-toggle.guard'; const routes: Routes = [ - // Basic CanActivate - requires authentication + // CanActivate básico - requiere autenticación { path: 'dashboard', component: DashboardComponent, canActivate: [authGuard] }, - // Multiple CanActivate guards - requires authentication AND admin role + // Múltiples guards CanActivate - requiere autenticación Y rol de admin { path: 'admin', component: AdminComponent, canActivate: [authGuard, adminGuard] }, - // CanActivate + CanDeactivate - protected route with unsaved changes check + // CanActivate + CanDeactivate - ruta protegida con verificación de cambios sin guardar { path: 'profile', component: ProfileComponent, @@ -180,26 +180,26 @@ const routes: Routes = [ canDeactivate: [canDeactivateGuard] }, - // CanActivateChild - protects all child routes + // CanActivateChild - protege todas las rutas hijas { - path: 'users', // /user - NOT protected + path: 'users', // /user - NO protegido canActivateChild: [authGuard], children: [ - // /users/list - PROTECTED + // /users/list - PROTEGIDO { path: 'list', component: UserListComponent }, - // /useres/detail/:id - PROTECTED + // /useres/detail/:id - PROTEGIDO { path: 'detail/:id', component: UserDetailComponent } ] }, - // CanMatch - conditionally matches route based on feature flag + // CanMatch - coincide condicionalmente con la ruta según feature flag { path: 'beta-feature', component: BetaFeatureComponent, canMatch: [featureToggleGuard] }, - // Fallback route if beta feature is disabled + // Ruta alternativa si la característica beta está deshabilitada { path: 'beta-feature', component: ComingSoonComponent diff --git a/adev-es/src/content/guide/routing/route-transition-animations.en.md b/adev-es/src/content/guide/routing/route-transition-animations.en.md new file mode 100644 index 0000000..4b372c2 --- /dev/null +++ b/adev-es/src/content/guide/routing/route-transition-animations.en.md @@ -0,0 +1,203 @@ +# Route transition animations + +Route transition animations enhance user experience by providing smooth visual transitions when navigating between different views in your Angular application. [Angular Router](/guide/routing/overview) includes built-in support for the browser's View Transitions API, enabling seamless animations between route changes in supported browsers. + +HELPFUL: The Router's native View Transitions integration is currently in [developer preview](/reference/releases#developer-preview). Native View Transitions are a relatively new browser feature with limited support across all browsers. + +## How View Transitions work + +View transitions use the browser's native [`document.startViewTransition` API](https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition) to create smooth animations between different states of your application. The API works by: + +1. **Capturing the current state** - The browser takes a screenshot of the current page +2. **Executing the DOM update** - Your callback function runs to update the DOM +3. **Capturing the new state** - The browser captures the updated page state +4. **Playing the transition** - The browser animates between the old and new states + +Here's the basic structure of the `startViewTransition` API: + +```ts +document.startViewTransition(async () => { + await updateTheDOMSomehow(); +}); +``` + +For more details about the browser API, see the [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions). + +## How the Router uses view transitions + +Angular Router integrates view transitions into the navigation lifecycle to create seamless route changes. During navigation, the Router: + +1. **Completes navigation preparation** - Route matching, [lazy loading](/guide/routing/define-routes#lazily-loaded-components), [guards](/guide/routing/route-guards), and [resolvers](/guide/routing/data-resolvers) execute +2. **Initiates the view transition** - Router calls `startViewTransition` when routes are ready for activation +3. **Updates the DOM** - Router activates new routes and deactivates old ones within the transition callback +4. **Finalizes the transition** - The transition Promise resolves when Angular completes rendering + +The Router's view transition integration acts as a [progressive enhancement](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement). When browsers don't support the View Transitions API, the Router performs normal DOM updates without animation, ensuring your application works across all browsers. + +## Enabling View Transitions in the Router + +Enable view transitions by adding the `withViewTransitions` feature to your [router configuration](/guide/routing/define-routes#adding-the-router-to-your-application). Angular supports both standalone and NgModule bootstrap approaches: + +### Standalone bootstrap + +```ts +import { bootstrapApplication } from '@angular/platform-browser'; +import { provideRouter, withViewTransitions } from '@angular/router'; +import { routes } from './app.routes'; + +bootstrapApplication(MyApp, { + providers: [ + provideRouter(routes, withViewTransitions()), + ] +}); +``` + +### NgModule bootstrap + +```ts +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +@NgModule({ + imports: [RouterModule.forRoot(routes, {enableViewTransitions: true})] +}) +export class AppRouting {} +``` + +[Try the "count" example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-2dnvtm?file=src%2Fmain.ts) + +This example demonstrates how router navigation can replace direct `startViewTransition` calls for counter updates. + +## Customizing transitions with CSS + +You can customize view transitions using CSS to create unique animation effects. The browser creates separate transition elements that you can target with CSS selectors. + +To create custom transitions: + +1. **Add view-transition-name** - Assign unique names to elements you want to animate +2. **Define global animations** - Create CSS animations in your global styles +3. **Target transition pseudo-elements** - Use `::view-transition-old()` and `::view-transition-new()` selectors + +Here's an example that adds a rotation effect to a counter element: + +```css +/* Define keyframe animations */ +@keyframes rotate-out { + to { + transform: rotate(90deg); + } +} + +@keyframes rotate-in { + from { + transform: rotate(-90deg); + } +} + +/* Target view transition pseudo-elements */ +::view-transition-old(count), +::view-transition-new(count) { + animation-duration: 200ms; + animation-name: -ua-view-transition-fade-in, rotate-in; +} + +::view-transition-old(count) { + animation-name: -ua-view-transition-fade-out, rotate-out; +} +``` + +IMPORTANT: Define view transition animations in your global styles file, not in component styles. Angular's [view encapsulation](/guide/components/styling#view-encapsulation) scopes component styles, which prevents them from targeting the transition pseudo-elements correctly. + +[Try the updated "count" example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-fwn4i7?file=src%2Fmain.ts) + +## Advanced transition control with onViewTransitionCreated + +The `withViewTransitions` feature accepts an options object with an `onViewTransitionCreated` callback for advanced control over view transitions. This callback: + +- Runs in an [injection context](/guide/di/dependency-injection-context#run-within-an-injection-context) +- Receives a [`ViewTransitionInfo`](/api/router/ViewTransitionInfo) object containing: + - The `ViewTransition` instance from `startViewTransition` + - The [`ActivatedRouteSnapshot`](/api/router/ActivatedRouteSnapshot) for the route being navigated from + - The [`ActivatedRouteSnapshot`](/api/router/ActivatedRouteSnapshot) for the route being navigated to + +Use this callback to customize transition behavior based on navigation context. For example, you can skip transitions for specific navigation types: + +```ts +import { inject } from '@angular/core'; +import { Router, withViewTransitions } from '@angular/router'; + +withViewTransitions({ + onViewTransitionCreated: ({transition}) => { + const router = inject(Router); + const targetUrl = router.getCurrentNavigation()!.finalUrl!; + + // Skip transition if only fragment or query params change + const config = { + paths: 'exact', + matrixParams: 'exact', + fragment: 'ignored', + queryParams: 'ignored', + }; + + if (router.isActive(targetUrl, config)) { + transition.skipTransition(); + } + }, +}) +``` + +This example skips the view transition when navigation only changes the [URL fragment or query parameters](/guide/routing/read-route-state#query-parameters) (such as anchor links within the same page). The `skipTransition()` method prevents the animation while still allowing the navigation to complete. + +## Examples from the Chrome explainer adapted to Angular + +The following examples demonstrate various view transition techniques adapted from the Chrome team's documentation for use with Angular Router: + +### Transitioning elements don't need to be the same DOM element + +Elements can transition smoothly between different DOM elements as long as they share the same `view-transition-name`. + +- [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#transitioning_elements_dont_need_to_be_the_same_dom_element) +- [Angular Example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-dh8npr?file=src%2Fmain.ts) + +### Custom entry and exit animations + +Create unique animations for elements entering and leaving the viewport during route transitions. + +- [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#custom_entry_and_exit_transitions) +- [Angular Example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-8kly3o) + +### Async DOM updates and waiting for content + +Angular Router prioritizes immediate transitions over waiting for additional content to load. + +- [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#async_dom_updates_and_waiting_for_content) + +NOTE: Angular Router does not provide a way to delay view transitions. This design choice prevents pages from becoming non-interactive while waiting for additional content. As the Chrome documentation notes: "During this time, the page is frozen, so delays here should be kept to a minimum…in some cases it's better to avoid the delay altogether, and use the content you already have." + +### Handle multiple view transition styles with view transition types + +Use view transition types to apply different animation styles based on navigation context. + +- [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#view-transition-types) +- [Angular Example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-vxzcam) + +### Handle multiple view transition styles with a class name on the view transition root (deprecated) + +This approach uses CSS classes on the transition root element to control animation styles. + +- [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#changing-on-navigation-type) +- [Angular Example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-nmnzzg?file=src%2Fmain.ts) + +### Transitioning without freezing other animations + +Maintain other page animations during view transitions to create more dynamic user experiences. + +- [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#transitioning-without-freezing) +- [Angular Example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-76kgww) + +### Animating with JavaScript + +Control view transitions programmatically using JavaScript APIs for complex animation scenarios. + +- [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#animating-with-javascript) +- [Angular Example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-cklnkm) diff --git a/adev-es/src/content/guide/routing/route-transition-animations.md b/adev-es/src/content/guide/routing/route-transition-animations.md index a9aa290..9a67229 100644 --- a/adev-es/src/content/guide/routing/route-transition-animations.md +++ b/adev-es/src/content/guide/routing/route-transition-animations.md @@ -1,19 +1,19 @@ -# Route transition animations +# Animaciones de transición de ruta -Route transition animations enhance user experience by providing smooth visual transitions when navigating between different views in your Angular application. [Angular Router](/guide/routing/overview) includes built-in support for the browser's View Transitions API, enabling seamless animations between route changes in supported browsers. +Las animaciones de transición de ruta mejoran la experiencia del usuario proporcionando transiciones visuales suaves al navegar entre diferentes vistas en tu aplicación Angular. [Angular Router](/guide/routing/overview) incluye soporte integrado para la API View Transitions del navegador, habilitando animaciones fluidas entre cambios de ruta en navegadores compatibles. -HELPFUL: The Router's native View Transitions integration is currently in [developer preview](/reference/releases#developer-preview). Native View Transitions are a relatively new browser feature with limited support across all browsers. +ÚTIL: La integración nativa de View Transitions del Router está actualmente en [developer preview](/reference/releases#developer-preview). Native View Transitions son una característica relativamente nueva del navegador con soporte limitado en todos los navegadores. -## How View Transitions work +## Cómo funcionan View Transitions -View transitions use the browser's native [`document.startViewTransition` API](https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition) to create smooth animations between different states of your application. The API works by: +View transitions usan la API nativa del navegador [`document.startViewTransition`](https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition) para crear animaciones suaves entre diferentes estados de tu aplicación. La API funciona mediante: -1. **Capturing the current state** - The browser takes a screenshot of the current page -2. **Executing the DOM update** - Your callback function runs to update the DOM -3. **Capturing the new state** - The browser captures the updated page state -4. **Playing the transition** - The browser animates between the old and new states +1. **Capturar el estado actual** - El navegador toma una captura de pantalla de la página actual +2. **Ejecutar la actualización del DOM** - Tu función de callback se ejecuta para actualizar el DOM +3. **Capturar el nuevo estado** - El navegador captura el estado de la página actualizada +4. **Reproducir la transición** - El navegador anima entre los estados antiguo y nuevo -Here's the basic structure of the `startViewTransition` API: +Aquí está la estructura básica de la API `startViewTransition`: ```ts document.startViewTransition(async () => { @@ -21,24 +21,24 @@ document.startViewTransition(async () => { }); ``` -For more details about the browser API, see the [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions). +Para más detalles sobre la API del navegador, consulta el [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions). -## How the Router uses view transitions +## Cómo el Router usa view transitions -Angular Router integrates view transitions into the navigation lifecycle to create seamless route changes. During navigation, the Router: +Angular Router integra view transitions en el ciclo de vida de navegación para crear cambios de ruta fluidos. Durante la navegación, el Router: -1. **Completes navigation preparation** - Route matching, [lazy loading](/guide/routing/define-routes#lazily-loaded-components), [guards](/guide/routing/route-guards), and [resolvers](/guide/routing/data-resolvers) execute -2. **Initiates the view transition** - Router calls `startViewTransition` when routes are ready for activation -3. **Updates the DOM** - Router activates new routes and deactivates old ones within the transition callback -4. **Finalizes the transition** - The transition Promise resolves when Angular completes rendering +1. **Completa la preparación de navegación** - Se ejecutan coincidencia de ruta, [lazy loading](/guide/routing/define-routes#lazily-loaded-components), [guards](/guide/routing/route-guards) y [resolvers](/guide/routing/data-resolvers) +2. **Inicia la view transition** - El Router llama a `startViewTransition` cuando las rutas están listas para activación +3. **Actualiza el DOM** - El Router activa nuevas rutas y desactiva las antiguas dentro del callback de transición +4. **Finaliza la transición** - La Promise de transición se resuelve cuando Angular completa la renderización -The Router's view transition integration acts as a [progressive enhancement](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement). When browsers don't support the View Transitions API, the Router performs normal DOM updates without animation, ensuring your application works across all browsers. +La integración de view transition del Router actúa como una [mejora progresiva](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement). Cuando los navegadores no soportan la API View Transitions, el Router realiza actualizaciones DOM normales sin animación, asegurando que tu aplicación funcione en todos los navegadores. -## Enabling View Transitions in the Router +## Habilitar View Transitions en el Router -Enable view transitions by adding the `withViewTransitions` feature to your [router configuration](/guide/routing/define-routes#adding-the-router-to-your-application). Angular supports both standalone and NgModule bootstrap approaches: +Habilita view transitions agregando la característica `withViewTransitions` a tu [configuración del router](/guide/routing/define-routes#adding-the-router-to-your-application). Angular soporta tanto enfoques de bootstrap standalone como NgModule: -### Standalone bootstrap +### Bootstrap standalone ```ts import { bootstrapApplication } from '@angular/platform-browser'; @@ -52,7 +52,7 @@ bootstrapApplication(MyApp, { }); ``` -### NgModule bootstrap +### Bootstrap NgModule ```ts import { NgModule } from '@angular/core'; @@ -64,24 +64,24 @@ import { RouterModule } from '@angular/router'; export class AppRouting {} ``` -[Try the "count" example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-2dnvtm?file=src%2Fmain.ts) +[Prueba el ejemplo "count" en StackBlitz](https://stackblitz.com/edit/stackblitz-starters-2dnvtm?file=src%2Fmain.ts) -This example demonstrates how router navigation can replace direct `startViewTransition` calls for counter updates. +Este ejemplo demuestra cómo la navegación del router puede reemplazar llamadas directas a `startViewTransition` para actualizaciones de contador. -## Customizing transitions with CSS +## Personalizar transiciones con CSS -You can customize view transitions using CSS to create unique animation effects. The browser creates separate transition elements that you can target with CSS selectors. +Puedes personalizar view transitions usando CSS para crear efectos de animación únicos. El navegador crea elementos de transición separados que puedes seleccionar con selectores CSS. -To create custom transitions: +Para crear transiciones personalizadas: -1. **Add view-transition-name** - Assign unique names to elements you want to animate -2. **Define global animations** - Create CSS animations in your global styles -3. **Target transition pseudo-elements** - Use `::view-transition-old()` and `::view-transition-new()` selectors +1. **Agregar view-transition-name** - Asigna nombres únicos a elementos que quieras animar +2. **Definir animaciones globales** - Crea animaciones CSS en tus estilos globales +3. **Seleccionar pseudo-elementos de transición** - Usa selectores `::view-transition-old()` y `::view-transition-new()` -Here's an example that adds a rotation effect to a counter element: +Aquí hay un ejemplo que agrega un efecto de rotación a un elemento contador: ```css -/* Define keyframe animations */ +/* Definir animaciones keyframe */ @keyframes rotate-out { to { transform: rotate(90deg); @@ -94,7 +94,7 @@ Here's an example that adds a rotation effect to a counter element: } } -/* Target view transition pseudo-elements */ +/* Seleccionar pseudo-elementos de view transition */ ::view-transition-old(count), ::view-transition-new(count) { animation-duration: 200ms; @@ -106,21 +106,21 @@ Here's an example that adds a rotation effect to a counter element: } ``` -IMPORTANT: Define view transition animations in your global styles file, not in component styles. Angular's [view encapsulation](/guide/components/styling#view-encapsulation) scopes component styles, which prevents them from targeting the transition pseudo-elements correctly. +IMPORTANTE: Define animaciones de view transition en tu archivo de estilos globales, no en estilos de componentes. La [encapsulación de vista](/guide/components/styling#view-encapsulation) de Angular limita el alcance de los estilos de componentes, lo que les impide seleccionar correctamente los pseudo-elementos de transición. -[Try the updated “count” example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-fwn4i7?file=src%2Fmain.ts) +[Prueba el ejemplo actualizado "count" en StackBlitz](https://stackblitz.com/edit/stackblitz-starters-fwn4i7?file=src%2Fmain.ts) -## Advanced transition control with onViewTransitionCreated +## Control avanzado de transición con onViewTransitionCreated -The `withViewTransitions` feature accepts an options object with an `onViewTransitionCreated` callback for advanced control over view transitions. This callback: +La característica `withViewTransitions` acepta un objeto de opciones con un callback `onViewTransitionCreated` para control avanzado sobre view transitions. Este callback: -- Runs in an [injection context](/guide/di/dependency-injection-context#run-within-an-injection-context) -- Receives a [`ViewTransitionInfo`](/api/router/ViewTransitionInfo) object containing: - - The `ViewTransition` instance from `startViewTransition` - - The [`ActivatedRouteSnapshot`](/api/router/ActivatedRouteSnapshot) for the route being navigated from - - The [`ActivatedRouteSnapshot`](/api/router/ActivatedRouteSnapshot) for the route being navigated to +- Se ejecuta en un [contexto de inyección](/guide/di/dependency-injection-context#run-within-an-injection-context) +- Recibe un objeto [`ViewTransitionInfo`](/api/router/ViewTransitionInfo) que contiene: + - La instancia `ViewTransition` de `startViewTransition` + - El [`ActivatedRouteSnapshot`](/api/router/ActivatedRouteSnapshot) para la ruta desde la que se está navegando + - El [`ActivatedRouteSnapshot`](/api/router/ActivatedRouteSnapshot) para la ruta a la que se está navegando -Use this callback to customize transition behavior based on navigation context. For example, you can skip transitions for specific navigation types: +Usa este callback para personalizar el comportamiento de transición basado en el contexto de navegación. Por ejemplo, puedes omitir transiciones para tipos específicos de navegación: ```ts import { inject } from '@angular/core'; @@ -131,7 +131,7 @@ withViewTransitions({ const router = inject(Router); const targetUrl = router.getCurrentNavigation()!.finalUrl!; - // Skip transition if only fragment or query params change + // Omitir transición si solo cambia el fragment o query params const config = { paths: 'exact', matrixParams: 'exact', @@ -146,58 +146,58 @@ withViewTransitions({ }) ``` -This example skips the view transition when navigation only changes the [URL fragment or query parameters](/guide/routing/read-route-state#query-parameters) (such as anchor links within the same page). The `skipTransition()` method prevents the animation while still allowing the navigation to complete. +Este ejemplo omite la view transition cuando la navegación solo cambia el [fragmento de URL o parámetros de consulta](/guide/routing/read-route-state#query-parameters) (como enlaces anchor dentro de la misma página). El método `skipTransition()` previene la animación mientras aún permite que la navegación se complete. -## Examples from the Chrome explainer adapted to Angular +## Ejemplos del Chrome explainer adaptados a Angular -The following examples demonstrate various view transition techniques adapted from the Chrome team's documentation for use with Angular Router: +Los siguientes ejemplos demuestran varias técnicas de view transition adaptadas de la documentación del equipo de Chrome para uso con Angular Router: -### Transitioning elements don't need to be the same DOM element +### Los elementos en transición no necesitan ser el mismo elemento DOM -Elements can transition smoothly between different DOM elements as long as they share the same `view-transition-name`. +Los elementos pueden hacer transición suavemente entre diferentes elementos DOM siempre que compartan el mismo `view-transition-name`. - [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#transitioning_elements_dont_need_to_be_the_same_dom_element) -- [Angular Example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-dh8npr?file=src%2Fmain.ts) +- [Ejemplo Angular en StackBlitz](https://stackblitz.com/edit/stackblitz-starters-dh8npr?file=src%2Fmain.ts) -### Custom entry and exit animations +### Animaciones personalizadas de entrada y salida -Create unique animations for elements entering and leaving the viewport during route transitions. +Crea animaciones únicas para elementos que entran y salen del viewport durante transiciones de ruta. - [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#custom_entry_and_exit_transitions) -- [Angular Example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-8kly3o) +- [Ejemplo Angular en StackBlitz](https://stackblitz.com/edit/stackblitz-starters-8kly3o) -### Async DOM updates and waiting for content +### Actualizaciones asíncronas del DOM y espera por contenido -Angular Router prioritizes immediate transitions over waiting for additional content to load. +Angular Router prioriza transiciones inmediatas sobre esperar a que se cargue contenido adicional. - [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#async_dom_updates_and_waiting_for_content) -NOTE: Angular Router does not provide a way to delay view transitions. This design choice prevents pages from becoming non-interactive while waiting for additional content. As the Chrome documentation notes: "During this time, the page is frozen, so delays here should be kept to a minimum…in some cases it's better to avoid the delay altogether, and use the content you already have." +NOTA: Angular Router no proporciona una forma de retrasar view transitions. Esta decisión de diseño previene que las páginas se vuelvan no interactivas mientras esperan contenido adicional. Como nota la documentación de Chrome: "Durante este tiempo, la página está congelada, por lo que los retrasos aquí deben mantenerse al mínimo...en algunos casos es mejor evitar el retraso por completo y usar el contenido que ya tienes." -### Handle multiple view transition styles with view transition types +### Manejar múltiples estilos de view transition con tipos de view transition -Use view transition types to apply different animation styles based on navigation context. +Usa tipos de view transition para aplicar diferentes estilos de animación basados en el contexto de navegación. - [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#view-transition-types) -- [Angular Example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-vxzcam) +- [Ejemplo Angular en StackBlitz](https://stackblitz.com/edit/stackblitz-starters-vxzcam) -### Handle multiple view transition styles with a class name on the view transition root (deprecated) +### Manejar múltiples estilos de view transition con un nombre de clase en la raíz de view transition (deprecado) -This approach uses CSS classes on the transition root element to control animation styles. +Este enfoque usa clases CSS en el elemento raíz de transición para controlar estilos de animación. - [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#changing-on-navigation-type) -- [Angular Example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-nmnzzg?file=src%2Fmain.ts) +- [Ejemplo Angular en StackBlitz](https://stackblitz.com/edit/stackblitz-starters-nmnzzg?file=src%2Fmain.ts) -### Transitioning without freezing other animations +### Transición sin congelar otras animaciones -Maintain other page animations during view transitions to create more dynamic user experiences. +Mantén otras animaciones de página durante view transitions para crear experiencias de usuario más dinámicas. - [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#transitioning-without-freezing) -- [Angular Example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-76kgww) +- [Ejemplo Angular en StackBlitz](https://stackblitz.com/edit/stackblitz-starters-76kgww) -### Animating with JavaScript +### Animar con JavaScript -Control view transitions programmatically using JavaScript APIs for complex animation scenarios. +Controla view transitions programáticamente usando APIs de JavaScript para escenarios de animación complejos. - [Chrome Explainer](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#animating-with-javascript) -- [Angular Example on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-cklnkm) +- [Ejemplo Angular en StackBlitz](https://stackblitz.com/edit/stackblitz-starters-cklnkm) diff --git a/adev-es/src/content/guide/routing/router-reference.en.md b/adev-es/src/content/guide/routing/router-reference.en.md new file mode 100644 index 0000000..03951d7 --- /dev/null +++ b/adev-es/src/content/guide/routing/router-reference.en.md @@ -0,0 +1,119 @@ +# Router reference + +The following sections highlight some core router concepts and terminology. + +## Router events + +During each navigation, the `Router` emits navigation events through the `Router.events` property. +These events are shown in the following table. + +| Router event | Details | +| :-------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [`NavigationStart`](api/router/NavigationStart) | Triggered when navigation starts. | +| [`RouteConfigLoadStart`](api/router/RouteConfigLoadStart) | Triggered before the `Router` lazy loads a route configuration. | +| [`RouteConfigLoadEnd`](api/router/RouteConfigLoadEnd) | Triggered after a route has been lazy loaded. | +| [`RoutesRecognized`](api/router/RoutesRecognized) | Triggered when the Router parses the URL and the routes are recognized. | +| [`GuardsCheckStart`](api/router/GuardsCheckStart) | Triggered when the Router begins the Guards phase of routing. | +| [`ChildActivationStart`](api/router/ChildActivationStart) | Triggered when the Router begins activating a route's children. | +| [`ActivationStart`](api/router/ActivationStart) | Triggered when the Router begins activating a route. | +| [`GuardsCheckEnd`](api/router/GuardsCheckEnd) | Triggered when the Router finishes the Guards phase of routing successfully. | +| [`ResolveStart`](api/router/ResolveStart) | Triggered when the Router begins the Resolve phase of routing. | +| [`ResolveEnd`](api/router/ResolveEnd) | Triggered when the Router finishes the Resolve phase of routing successfully. | +| [`ChildActivationEnd`](api/router/ChildActivationEnd) | Triggered when the Router finishes activating a route's children. | +| [`ActivationEnd`](api/router/ActivationEnd) | Triggered when the Router finishes activating a route. | +| [`NavigationEnd`](api/router/NavigationEnd) | Triggered when navigation ends successfully. | +| [`NavigationCancel`](api/router/NavigationCancel) | Triggered when navigation is canceled. This can happen when a Route Guard returns false during navigation, or redirects by returning a `UrlTree` or `RedirectCommand`. | +| [`NavigationError`](api/router/NavigationError) | Triggered when navigation fails due to an unexpected error. | +| [`Scroll`](api/router/Scroll) | Represents a scrolling event. | + +When you enable the `withDebugTracing` feature, Angular logs these events to the console. + +## Router terminology + +Here are the key `Router` terms and their meanings: + +| Router part | Details | +| :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Router` | Displays the application component for the active URL. Manages navigation from one component to the next. | +| `provideRouter` | provides the necessary service providers for navigating through application views. | +| `RouterModule` | A separate NgModule that provides the necessary service providers and directives for navigating through application views. | +| `Routes` | Defines an array of Routes, each mapping a URL path to a component. | +| `Route` | Defines how the router should navigate to a component based on a URL pattern. Most routes consist of a path and a component type. | +| `RouterOutlet` | The directive \(``\) that marks where the router displays a view. | +| `RouterLink` | The directive for binding a clickable HTML element to a route. Clicking an element with a `routerLink` directive that's bound to a _string_ or a _link parameters array_ triggers a navigation. | +| `RouterLinkActive` | The directive for adding/removing classes from an HTML element when an associated `routerLink` contained on or inside the element becomes active/inactive. It can also set the `aria-current` of an active link for better accessibility. | +| `ActivatedRoute` | A service that's provided to each route component that contains route specific information such as route parameters, static data, resolve data, global query parameters, and the global fragment. | +| `RouterState` | The current state of the router including a tree of the currently activated routes together with convenience methods for traversing the route tree. | +| Link parameters array | An array that the router interprets as a routing instruction. You can bind that array to a `RouterLink` or pass the array as an argument to the `Router.navigate` method. | +| Routing component | An Angular component with a `RouterOutlet` that displays views based on router navigations. | + +## `` + +The router uses the browser's [history.pushState](https://developer.mozilla.org/docs/Web/API/History_API/Working_with_the_History_API#adding_and_modifying_history_entries 'HTML5 browser history push-state') for navigation. +`pushState` lets you customize in-application URL paths; for example, `localhost:4200/crisis-center`. +The in-application URLs can be indistinguishable from server URLs. + +Modern HTML5 browsers were the first to support `pushState` which is why many people refer to these URLs as "HTML5 style" URLs. + +HELPFUL: HTML5 style navigation is the router default. +In the [LocationStrategy and browser URL styles](#locationstrategy-and-browser-url-styles) section, learn why HTML5 style is preferable, how to adjust its behavior, and how to switch to the older hash \(`#`\) style, if necessary. + +You must add a [`` element](https://developer.mozilla.org/docs/Web/HTML/Element/base 'base href') to the application's `index.html` for `pushState` routing to work. +The browser uses the `` value to prefix relative URLs when referencing CSS files, scripts, and images. + +Add the `` element just after the `` tag. +If the `app` folder is the application root, as it is for this application, set the `href` value in `index.html` as shown here. + + + +### HTML5 URLs and the `` + +The guidelines that follow will refer to different parts of a URL. +This diagram outlines what those parts refer to: + + +foo://example.com:8042/over/there?name=ferret#nose +\_/ \______________/\_________/ \_________/ \__/ + | | | | | +scheme authority path query fragment + + +While the router uses the [HTML5 pushState](https://developer.mozilla.org/docs/Web/API/History_API#Adding_and_modifying_history_entries 'Browser history push-state') style by default, you must configure that strategy with a ``. + +The preferred way to configure the strategy is to add a [`` element](https://developer.mozilla.org/docs/Web/HTML/Element/base 'base href') tag in the `` of the `index.html`. + +```angular-html + +``` + +Without that tag, the browser might not be able to load resources \(images, CSS, scripts\) when "deep linking" into the application. + +Some developers might not be able to add the `` element, perhaps because they don't have access to `` or the `index.html`. + +Those developers can still use HTML5 URLs by taking the following two steps: + +1. Provide the router with an appropriate `APP_BASE_HREF` value. +1. Use root URLs \(URLs with an `authority`\) for all web resources: CSS, images, scripts, and template HTML files. + + - The `` `path` should end with a "/", as browsers ignore characters in the `path` that follow the right-most "`/`" + - If the `` includes a `query` part, the `query` is only used if the `path` of a link in the page is empty and has no `query`. + This means that a `query` in the `` is only included when using `HashLocationStrategy`. + + - If a link in the page is a root URL \(has an `authority`\), the `` is not used. + In this way, an `APP_BASE_HREF` with an authority will cause all links created by Angular to ignore the `` value. + + - A fragment in the `` is _never_ persisted + +For more complete information on how `` is used to construct target URIs, see the [RFC](https://tools.ietf.org/html/rfc3986#section-5.2.2) section on transforming references. + +### `HashLocationStrategy` + +Use `HashLocationStrategy` by providing the `useHash: true` in an object as the second argument of the `RouterModule.forRoot()` in the `AppModule`. + +```ts +providers: [ + provideRouter(appRoutes, withHashLocation()) +] +``` + +When using `RouterModule.forRoot`, this is configured with the `useHash: true` in the second argument: `RouterModule.forRoot(routes, {useHash: true})`. diff --git a/adev-es/src/content/guide/routing/router-reference.md b/adev-es/src/content/guide/routing/router-reference.md index 03951d7..fed072a 100644 --- a/adev-es/src/content/guide/routing/router-reference.md +++ b/adev-es/src/content/guide/routing/router-reference.md @@ -1,75 +1,75 @@ -# Router reference +# Referencia del Router -The following sections highlight some core router concepts and terminology. +Las siguientes secciones destacan algunos conceptos y terminología centrales del router. -## Router events +## Eventos del Router -During each navigation, the `Router` emits navigation events through the `Router.events` property. -These events are shown in the following table. +Durante cada navegación, el `Router` emite eventos de navegación a través de la propiedad `Router.events`. +Estos eventos se muestran en la siguiente tabla. -| Router event | Details | +| Evento del Router | Detalles | | :-------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [`NavigationStart`](api/router/NavigationStart) | Triggered when navigation starts. | -| [`RouteConfigLoadStart`](api/router/RouteConfigLoadStart) | Triggered before the `Router` lazy loads a route configuration. | -| [`RouteConfigLoadEnd`](api/router/RouteConfigLoadEnd) | Triggered after a route has been lazy loaded. | -| [`RoutesRecognized`](api/router/RoutesRecognized) | Triggered when the Router parses the URL and the routes are recognized. | -| [`GuardsCheckStart`](api/router/GuardsCheckStart) | Triggered when the Router begins the Guards phase of routing. | -| [`ChildActivationStart`](api/router/ChildActivationStart) | Triggered when the Router begins activating a route's children. | -| [`ActivationStart`](api/router/ActivationStart) | Triggered when the Router begins activating a route. | -| [`GuardsCheckEnd`](api/router/GuardsCheckEnd) | Triggered when the Router finishes the Guards phase of routing successfully. | -| [`ResolveStart`](api/router/ResolveStart) | Triggered when the Router begins the Resolve phase of routing. | -| [`ResolveEnd`](api/router/ResolveEnd) | Triggered when the Router finishes the Resolve phase of routing successfully. | -| [`ChildActivationEnd`](api/router/ChildActivationEnd) | Triggered when the Router finishes activating a route's children. | -| [`ActivationEnd`](api/router/ActivationEnd) | Triggered when the Router finishes activating a route. | -| [`NavigationEnd`](api/router/NavigationEnd) | Triggered when navigation ends successfully. | -| [`NavigationCancel`](api/router/NavigationCancel) | Triggered when navigation is canceled. This can happen when a Route Guard returns false during navigation, or redirects by returning a `UrlTree` or `RedirectCommand`. | -| [`NavigationError`](api/router/NavigationError) | Triggered when navigation fails due to an unexpected error. | -| [`Scroll`](api/router/Scroll) | Represents a scrolling event. | - -When you enable the `withDebugTracing` feature, Angular logs these events to the console. - -## Router terminology - -Here are the key `Router` terms and their meanings: - -| Router part | Details | +| [`NavigationStart`](api/router/NavigationStart) | Se dispara cuando comienza la navegación. | +| [`RouteConfigLoadStart`](api/router/RouteConfigLoadStart) | Se dispara antes de que el `Router` cargue de forma diferida una configuración de ruta. | +| [`RouteConfigLoadEnd`](api/router/RouteConfigLoadEnd) | Se dispara después de que una ruta ha sido cargada de forma diferida. | +| [`RoutesRecognized`](api/router/RoutesRecognized) | Se dispara cuando el Router parsea la URL y las rutas son reconocidas. | +| [`GuardsCheckStart`](api/router/GuardsCheckStart) | Se dispara cuando el Router comienza la fase de Guards del enrutamiento. | +| [`ChildActivationStart`](api/router/ChildActivationStart) | Se dispara cuando el Router comienza a activar los hijos de una ruta. | +| [`ActivationStart`](api/router/ActivationStart) | Se dispara cuando el Router comienza a activar una ruta. | +| [`GuardsCheckEnd`](api/router/GuardsCheckEnd) | Se dispara cuando el Router finaliza la fase de Guards del enrutamiento exitosamente. | +| [`ResolveStart`](api/router/ResolveStart) | Se dispara cuando el Router comienza la fase de Resolve del enrutamiento. | +| [`ResolveEnd`](api/router/ResolveEnd) | Se dispara cuando el Router finaliza la fase de Resolve del enrutamiento exitosamente. | +| [`ChildActivationEnd`](api/router/ChildActivationEnd) | Se dispara cuando el Router finaliza la activación de los hijos de una ruta. | +| [`ActivationEnd`](api/router/ActivationEnd) | Se dispara cuando el Router finaliza la activación de una ruta. | +| [`NavigationEnd`](api/router/NavigationEnd) | Se dispara cuando la navegación finaliza exitosamente. | +| [`NavigationCancel`](api/router/NavigationCancel) | Se dispara cuando la navegación se cancela. Esto puede suceder cuando un Route Guard retorna false durante la navegación, o redirige retornando un `UrlTree` o `RedirectCommand`. | +| [`NavigationError`](api/router/NavigationError) | Se dispara cuando la navegación falla debido a un error inesperado. | +| [`Scroll`](api/router/Scroll) | Representa un evento de scrolling. | + +Cuando habilitas la característica `withDebugTracing`, Angular registra estos eventos en la consola. + +## Terminología del Router + +Aquí están los términos clave del `Router` y sus significados: + +| Parte del Router | Detalles | | :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `Router` | Displays the application component for the active URL. Manages navigation from one component to the next. | -| `provideRouter` | provides the necessary service providers for navigating through application views. | -| `RouterModule` | A separate NgModule that provides the necessary service providers and directives for navigating through application views. | -| `Routes` | Defines an array of Routes, each mapping a URL path to a component. | -| `Route` | Defines how the router should navigate to a component based on a URL pattern. Most routes consist of a path and a component type. | -| `RouterOutlet` | The directive \(``\) that marks where the router displays a view. | -| `RouterLink` | The directive for binding a clickable HTML element to a route. Clicking an element with a `routerLink` directive that's bound to a _string_ or a _link parameters array_ triggers a navigation. | -| `RouterLinkActive` | The directive for adding/removing classes from an HTML element when an associated `routerLink` contained on or inside the element becomes active/inactive. It can also set the `aria-current` of an active link for better accessibility. | -| `ActivatedRoute` | A service that's provided to each route component that contains route specific information such as route parameters, static data, resolve data, global query parameters, and the global fragment. | -| `RouterState` | The current state of the router including a tree of the currently activated routes together with convenience methods for traversing the route tree. | -| Link parameters array | An array that the router interprets as a routing instruction. You can bind that array to a `RouterLink` or pass the array as an argument to the `Router.navigate` method. | -| Routing component | An Angular component with a `RouterOutlet` that displays views based on router navigations. | +| `Router` | Muestra el componente de aplicación para la URL activa. Gestiona la navegación de un componente al siguiente. | +| `provideRouter` | proporciona los proveedores de servicio necesarios para navegar a través de las vistas de la aplicación. | +| `RouterModule` | Un NgModule separado que proporciona los proveedores de servicio y directivas necesarias para navegar a través de las vistas de la aplicación. | +| `Routes` | Define un array de Routes, cada una mapeando una ruta de URL a un componente. | +| `Route` | Define cómo el router debe navegar a un componente basándose en un patrón de URL. La mayoría de las rutas consisten en una ruta y un tipo de componente. | +| `RouterOutlet` | La directiva \(``\) que marca dónde el router muestra una vista. | +| `RouterLink` | La directiva para vincular un elemento HTML clickeable a una ruta. Hacer clic en un elemento con una directiva `routerLink` que está vinculada a un _string_ o un _array de parámetros de enlace_ dispara una navegación. | +| `RouterLinkActive` | La directiva para agregar/eliminar clases de un elemento HTML cuando un `routerLink` asociado contenido en o dentro del elemento se vuelve activo/inactivo. También puede establecer el `aria-current` de un enlace activo para mejor accesibilidad. | +| `ActivatedRoute` | Un servicio que se proporciona a cada componente de ruta que contiene información específica de la ruta como parámetros de ruta, datos estáticos, datos resueltos, parámetros de consulta globales y el fragmento global. | +| `RouterState` | El estado actual del router incluyendo un árbol de las rutas actualmente activadas junto con métodos de conveniencia para recorrer el árbol de rutas. | +| Array de parámetros de enlace | Un array que el router interpreta como una instrucción de enrutamiento. Puedes vincular ese array a un `RouterLink` o pasar el array como argumento al método `Router.navigate`. | +| Componente de enrutamiento | Un componente Angular con un `RouterOutlet` que muestra vistas basadas en navegaciones del router. | ## `` -The router uses the browser's [history.pushState](https://developer.mozilla.org/docs/Web/API/History_API/Working_with_the_History_API#adding_and_modifying_history_entries 'HTML5 browser history push-state') for navigation. -`pushState` lets you customize in-application URL paths; for example, `localhost:4200/crisis-center`. -The in-application URLs can be indistinguishable from server URLs. +El router usa el [history.pushState](https://developer.mozilla.org/docs/Web/API/History_API/Working_with_the_History_API#adding_and_modifying_history_entries 'HTML5 browser history push-state') del navegador para navegación. +`pushState` te permite personalizar rutas de URL dentro de la aplicación; por ejemplo, `localhost:4200/crisis-center`. +Las URLs dentro de la aplicación pueden ser indistinguibles de las URLs del servidor. -Modern HTML5 browsers were the first to support `pushState` which is why many people refer to these URLs as "HTML5 style" URLs. +Los navegadores HTML5 modernos fueron los primeros en soportar `pushState`, razón por la cual muchas personas se refieren a estas URLs como URLs "estilo HTML5". -HELPFUL: HTML5 style navigation is the router default. -In the [LocationStrategy and browser URL styles](#locationstrategy-and-browser-url-styles) section, learn why HTML5 style is preferable, how to adjust its behavior, and how to switch to the older hash \(`#`\) style, if necessary. +ÚTIL: La navegación estilo HTML5 es el valor predeterminado del router. +En la sección [LocationStrategy y estilos de URL del navegador](#locationstrategy-and-browser-url-styles), aprende por qué el estilo HTML5 es preferable, cómo ajustar su comportamiento y cómo cambiar al estilo hash \(`#`\) más antiguo, si es necesario. -You must add a [`` element](https://developer.mozilla.org/docs/Web/HTML/Element/base 'base href') to the application's `index.html` for `pushState` routing to work. -The browser uses the `` value to prefix relative URLs when referencing CSS files, scripts, and images. +Debes agregar un [elemento ``](https://developer.mozilla.org/docs/Web/HTML/Element/base 'base href') al `index.html` de la aplicación para que el enrutamiento `pushState` funcione. +El navegador usa el valor `` para prefijar URLs relativas al referenciar archivos CSS, scripts e imágenes. -Add the `` element just after the `` tag. -If the `app` folder is the application root, as it is for this application, set the `href` value in `index.html` as shown here. +Agrega el elemento `` justo después de la etiqueta ``. +Si la carpeta `app` es la raíz de la aplicación, como lo es para esta aplicación, establece el valor `href` en `index.html` como se muestra aquí. -### HTML5 URLs and the `` +### URLs HTML5 y el `` -The guidelines that follow will refer to different parts of a URL. -This diagram outlines what those parts refer to: +Las directrices que siguen se referirán a diferentes partes de una URL. +Este diagrama describe a qué se refieren esas partes: foo://example.com:8042/over/there?name=ferret#nose @@ -78,37 +78,37 @@ foo://example.com:8042/over/there?name=ferret#nose scheme authority path query fragment -While the router uses the [HTML5 pushState](https://developer.mozilla.org/docs/Web/API/History_API#Adding_and_modifying_history_entries 'Browser history push-state') style by default, you must configure that strategy with a ``. +Aunque el router usa el estilo [HTML5 pushState](https://developer.mozilla.org/docs/Web/API/History_API#Adding_and_modifying_history_entries 'Browser history push-state') por defecto, debes configurar esa estrategia con un ``. -The preferred way to configure the strategy is to add a [`` element](https://developer.mozilla.org/docs/Web/HTML/Element/base 'base href') tag in the `` of the `index.html`. +La forma preferida de configurar la estrategia es agregar una etiqueta [elemento ``](https://developer.mozilla.org/docs/Web/HTML/Element/base 'base href') en el `` del `index.html`. ```angular-html ``` -Without that tag, the browser might not be able to load resources \(images, CSS, scripts\) when "deep linking" into the application. +Sin esa etiqueta, el navegador podría no poder cargar recursos \(imágenes, CSS, scripts\) cuando se haga "deep linking" en la aplicación. -Some developers might not be able to add the `` element, perhaps because they don't have access to `` or the `index.html`. +Algunos desarrolladores podrían no poder agregar el elemento ``, quizás porque no tienen acceso al `` o al `index.html`. -Those developers can still use HTML5 URLs by taking the following two steps: +Esos desarrolladores aún pueden usar URLs HTML5 siguiendo los siguientes dos pasos: -1. Provide the router with an appropriate `APP_BASE_HREF` value. -1. Use root URLs \(URLs with an `authority`\) for all web resources: CSS, images, scripts, and template HTML files. +1. Proporciona al router un valor `APP_BASE_HREF` apropiado. +1. Usa URLs raíz \(URLs con un `authority`\) para todos los recursos web: CSS, imágenes, scripts y archivos HTML de plantilla. - - The `` `path` should end with a "/", as browsers ignore characters in the `path` that follow the right-most "`/`" - - If the `` includes a `query` part, the `query` is only used if the `path` of a link in the page is empty and has no `query`. - This means that a `query` in the `` is only included when using `HashLocationStrategy`. + - El `path` de `` debe terminar con un "/", ya que los navegadores ignoran caracteres en el `path` que siguen al "`/`" más a la derecha + - Si el `` incluye una parte `query`, el `query` solo se usa si el `path` de un enlace en la página está vacío y no tiene `query`. + Esto significa que un `query` en el `` solo se incluye cuando se usa `HashLocationStrategy`. - - If a link in the page is a root URL \(has an `authority`\), the `` is not used. - In this way, an `APP_BASE_HREF` with an authority will cause all links created by Angular to ignore the `` value. + - Si un enlace en la página es una URL raíz \(tiene un `authority`\), el `` no se usa. + De esta manera, un `APP_BASE_HREF` con un authority causará que todos los enlaces creados por Angular ignoren el valor ``. - - A fragment in the `` is _never_ persisted + - Un fragmento en el `` _nunca_ se persiste -For more complete information on how `` is used to construct target URIs, see the [RFC](https://tools.ietf.org/html/rfc3986#section-5.2.2) section on transforming references. +Para información más completa sobre cómo `` se usa para construir URIs objetivo, consulta la sección [RFC](https://tools.ietf.org/html/rfc3986#section-5.2.2) sobre transformación de referencias. ### `HashLocationStrategy` -Use `HashLocationStrategy` by providing the `useHash: true` in an object as the second argument of the `RouterModule.forRoot()` in the `AppModule`. +Usa `HashLocationStrategy` proporcionando el `useHash: true` en un objeto como segundo argumento del `RouterModule.forRoot()` en el `AppModule`. ```ts providers: [ @@ -116,4 +116,4 @@ providers: [ ] ``` -When using `RouterModule.forRoot`, this is configured with the `useHash: true` in the second argument: `RouterModule.forRoot(routes, {useHash: true})`. +Cuando usas `RouterModule.forRoot`, esto se configura con el `useHash: true` en el segundo argumento: `RouterModule.forRoot(routes, {useHash: true})`. diff --git a/adev-es/src/content/guide/routing/router-tutorial.en.md b/adev-es/src/content/guide/routing/router-tutorial.en.md new file mode 100644 index 0000000..9b0bd46 --- /dev/null +++ b/adev-es/src/content/guide/routing/router-tutorial.en.md @@ -0,0 +1,275 @@ +# Using Angular routes in a single-page application + +This tutorial describes how to build a single-page application, SPA that uses multiple Angular routes. + +In a Single Page Application \(SPA\), all of your application's functions exist in a single HTML page. +As users access your application's features, the browser needs to render only the parts that matter to the user, instead of loading a new page. +This pattern can significantly improve your application's user experience. + +To define how users navigate through your application, you use routes. +Add routes to define how users navigate from one part of your application to another. +You can also configure routes to guard against unexpected or unauthorized behavior. + +## Objectives + +* Organize a sample application's features into modules. +* Define how to navigate to a component. +* Pass information to a component using a parameter. +* Structure routes by nesting several routes. +* Check whether users can access a route. +* Control whether the application can discard unsaved changes. +* Improve performance by pre-fetching route data and lazy loading feature modules. +* Require specific criteria to load components. + +## Create a sample application + +Using the Angular CLI, create a new application, *angular-router-sample*. +This application will have two components: *crisis-list* and *heroes-list*. + +1. Create a new Angular project, *angular-router-sample*. + + + ng new angular-router-sample + + + When prompted with `Would you like to add Angular routing?`, select `N`. + + When prompted with `Which stylesheet format would you like to use?`, select `CSS`. + + After a few moments, a new project, `angular-router-sample`, is ready. + +1. From your terminal, navigate to the `angular-router-sample` directory. +1. Create a component, *crisis-list*. + + + ng generate component crisis-list + + +1. In your code editor, locate the file, `crisis-list.component.html` and replace the placeholder content with the following HTML. + + + +1. Create a second component, *heroes-list*. + + + ng generate component heroes-list + + +1. In your code editor, locate the file, `heroes-list.component.html` and replace the placeholder content with the following HTML. + + + +1. In your code editor, open the file, `app.component.html` and replace its contents with the following HTML. + + + +1. Verify that your new application runs as expected by running the `ng serve` command. + + + ng serve + + +1. Open a browser to `http://localhost:4200`. + + You should see a single web page, consisting of a title and the HTML of your two components. + +## Define your routes + +In this section, you'll define two routes: + +* The route `/crisis-center` opens the `crisis-center` component. +* The route `/heroes-list` opens the `heroes-list` component. + +A route definition is a JavaScript object. +Each route typically has two properties. +The first property, `path`, is a string that specifies the URL path for the route. +The second property, `component`, is a string that specifies what component your application should display for that path. + +1. From your code editor, create and open the `app.routes.ts` file. +1. Create and export a routes list for your application: + + ```ts + import {Routes} from '@angular/router'; + + export const routes = []; + ``` + +1. Add two routes for your first two components: + + ```ts + {path: 'crisis-list', component: CrisisListComponent}, + {path: 'heroes-list', component: HeroesListComponent}, + ``` + +This routes list is an array of JavaScript objects, with each object defining the properties of a route. + +## Import `provideRouter` from `@angular/router` + +Routing lets you display specific views of your application depending on the URL path. +To add this functionality to your sample application, you need to update the `app.config.ts` file to use the router providers function, `provideRouter`. +You import this provider function from `@angular/router`. + +1. From your code editor, open the `app.config.ts` file. +1. Add the following import statements: + + ```ts + import { provideRouter } from '@angular/router'; + import { routes } from './app.routes'; + ``` + +1. Update the providers in the `appConfig`: + + ```ts + providers: [provideRouter(routes)] + ``` + +For `NgModule` based applications, put the `provideRouter` in the `providers` list of the `AppModule`, or whichever module is passed to `bootstrapModule` in the application. + +## Update your component with `router-outlet` + +At this point, you have defined two routes for your application. +However, your application still has both the `crisis-list` and `heroes-list` components hard-coded in your `app.component.html` template. +For your routes to work, you need to update your template to dynamically load a component based on the URL path. + +To implement this functionality, you add the `router-outlet` directive to your template file. + +1. From your code editor, open the `app.component.html` file. +1. Delete the following lines. + + + +1. Add the `router-outlet` directive. + + + +1. Add `RouterOutlet` to the imports of the `AppComponent` in `app.component.ts` + + ```ts + imports: [RouterOutlet], + ``` + +View your updated application in your browser. +You should see only the application title. +To view the `crisis-list` component, add `crisis-list` to the end of the path in your browser's address bar. +For example: + + +http://localhost:4200/crisis-list + + +Notice that the `crisis-list` component displays. +Angular is using the route you defined to dynamically load the component. +You can load the `heroes-list` component the same way: + + +http://localhost:4200/heroes-list + + +## Control navigation with UI elements + +Currently, your application supports two routes. +However, the only way to use those routes is for the user to manually type the path in the browser's address bar. +In this section, you'll add two links that users can click to navigate between the `heroes-list` and `crisis-list` components. +You'll also add some CSS styles. +While these styles are not required, they make it easier to identify the link for the currently-displayed component. +You'll add that functionality in the next section. + +1. Open the `app.component.html` file and add the following HTML below the title. + + + + This HTML uses an Angular directive, `routerLink`. + This directive connects the routes you defined to your template files. + +1. Add the `RouterLink` directive to the imports list of `AppComponent` in `app.component.ts`. + +1. Open the `app.component.css` file and add the following styles. + + + +If you view your application in the browser, you should see these two links. +When you click on a link, the corresponding component appears. + +## Identify the active route + +While users can navigate your application using the links you added in the previous section, they don't have a straightforward way to identify what the active route is. +Add this functionality using Angular's `routerLinkActive` directive. + +1. From your code editor, open the `app.component.html` file. +1. Update the anchor tags to include the `routerLinkActive` directive. + + +1. Add the `RouterLinkActive` directive to the `imports` list of `AppComponent` in `app.component.ts`. + +View your application again. +As you click one of the buttons, the style for that button updates automatically, identifying the active component to the user. +By adding the `routerLinkActive` directive, you inform your application to apply a specific CSS class to the active route. +In this tutorial, that CSS class is `activebutton`, but you could use any class that you want. + +Note that we are also specifying a value for the `routerLinkActive`'s `ariaCurrentWhenActive`. This makes sure that visually impaired users (which may not perceive the different styling being applied) can also identify the active button. For more information see the Accessibility Best Practices [Active links identification section](/best-practices/a11y#active-links-identification). + +## Adding a redirect + +In this step of the tutorial, you add a route that redirects the user to display the `/heroes-list` component. + +1. From your code editor, open the `app.routes.ts` file. +1. Update the `routes` section as follows. + + ```ts + {path: '', redirectTo: '/heroes-list', pathMatch: 'full'}, + ``` + + Notice that this new route uses an empty string as its path. + In addition, it replaces the `component` property with two new ones: + + | Properties | Details | + |:--- |:--- | + | `redirectTo` | This property instructs Angular to redirect from an empty path to the `heroes-list` path. | + | `pathMatch` | This property instructs Angular on how much of the URL to match. For this tutorial, you should set this property to `full`. This strategy is recommended when you have an empty string for a path. For more information about this property, see the [Route API documentation](api/router/Route). | + +Now when you open your application, it displays the `heroes-list` component by default. + +## Adding a 404 page + +It is possible for a user to try to access a route that you have not defined. +To account for this behavior, the best practice is to display a 404 page. +In this section, you'll create a 404 page and update your route configuration to show that page for any unspecified routes. + +1. From the terminal, create a new component, `PageNotFound`. + + + ng generate component page-not-found + + +1. From your code editor, open the `page-not-found.component.html` file and replace its contents with the following HTML. + + + +1. Open the `app.routes.ts` file and add the following route to the routes list: + + ```ts + {path: '**', component: PageNotFoundComponent} + ``` + + The new route uses a path, `**`. + This path is how Angular identifies a wildcard route. + Any route that does not match an existing route in your configuration will use this route. + +IMPORTANT: Notice that the wildcard route is placed at the end of the array. +The order of your routes is important, as Angular applies routes in order and uses the first match it finds. + +Try navigating to a non-existing route on your application, such as `http://localhost:4200/powers`. +This route doesn't match anything defined in your `app.routes.ts` file. +However, because you defined a wildcard route, the application automatically displays your `PageNotFound` component. + +## Next steps + +At this point, you have a basic application that uses Angular's routing feature to change what components the user can see based on the URL address. +You have extended these features to include a redirect, as well as a wildcard route to display a custom 404 page. + +For more information about routing, see the following topics: + + + + + diff --git a/adev-es/src/content/guide/routing/router-tutorial.md b/adev-es/src/content/guide/routing/router-tutorial.md index 9b0bd46..07a3e46 100644 --- a/adev-es/src/content/guide/routing/router-tutorial.md +++ b/adev-es/src/content/guide/routing/router-tutorial.md @@ -1,92 +1,92 @@ -# Using Angular routes in a single-page application +# Usar rutas de Angular en una aplicación de página única (SPA) -This tutorial describes how to build a single-page application, SPA that uses multiple Angular routes. +Este tutorial describe cómo construir una aplicación de página única, SPA que usa múltiples rutas de Angular. -In a Single Page Application \(SPA\), all of your application's functions exist in a single HTML page. -As users access your application's features, the browser needs to render only the parts that matter to the user, instead of loading a new page. -This pattern can significantly improve your application's user experience. +En una Single Page Application \(SPA\), todas las funciones de tu aplicación existen en una sola página HTML. +A medida que los usuarios acceden a las características de tu aplicación, el navegador solo necesita renderizar las partes que importan al usuario, en lugar de cargar una nueva página. +Este patrón puede mejorar significativamente la experiencia del usuario de tu aplicación. -To define how users navigate through your application, you use routes. -Add routes to define how users navigate from one part of your application to another. -You can also configure routes to guard against unexpected or unauthorized behavior. +Para definir cómo los usuarios navegan a través de tu aplicación, usas rutas. +Agrega rutas para definir cómo los usuarios navegan de una parte de tu aplicación a otra. +También puedes configurar rutas para protegerse contra comportamientos inesperados o no autorizados. -## Objectives +## Objetivos -* Organize a sample application's features into modules. -* Define how to navigate to a component. -* Pass information to a component using a parameter. -* Structure routes by nesting several routes. -* Check whether users can access a route. -* Control whether the application can discard unsaved changes. -* Improve performance by pre-fetching route data and lazy loading feature modules. -* Require specific criteria to load components. +* Organizar las características de una aplicación de ejemplo en módulos. +* Definir cómo navegar a un componente. +* Pasar información a un componente usando un parámetro. +* Estructurar rutas anidando varias rutas. +* Verificar si los usuarios pueden acceder a una ruta. +* Controlar si la aplicación puede descartar cambios no guardados. +* Mejorar el rendimiento precargando datos de ruta y cargando módulos de características con lazy loading. +* Requerir criterios específicos para cargar componentes. -## Create a sample application +## Crear una aplicación de ejemplo -Using the Angular CLI, create a new application, *angular-router-sample*. -This application will have two components: *crisis-list* and *heroes-list*. +Usando Angular CLI, crea una nueva aplicación, *angular-router-sample*. +Esta aplicación tendrá dos componentes: *crisis-list* y *heroes-list*. -1. Create a new Angular project, *angular-router-sample*. +1. Crea un nuevo proyecto Angular, *angular-router-sample*. ng new angular-router-sample - When prompted with `Would you like to add Angular routing?`, select `N`. + Cuando se te pregunte `Would you like to add Angular routing?`, selecciona `N`. - When prompted with `Which stylesheet format would you like to use?`, select `CSS`. + Cuando se te pregunte `Which stylesheet format would you like to use?`, selecciona `CSS`. - After a few moments, a new project, `angular-router-sample`, is ready. + Después de unos momentos, un nuevo proyecto, `angular-router-sample`, estará listo. -1. From your terminal, navigate to the `angular-router-sample` directory. -1. Create a component, *crisis-list*. +1. Desde tu terminal, navega al directorio `angular-router-sample`. +1. Crea un componente, *crisis-list*. ng generate component crisis-list -1. In your code editor, locate the file, `crisis-list.component.html` and replace the placeholder content with the following HTML. +1. En tu editor de código, localiza el archivo `crisis-list.component.html` y reemplaza el contenido placeholder con el siguiente HTML. -1. Create a second component, *heroes-list*. +1. Crea un segundo componente, *heroes-list*. ng generate component heroes-list -1. In your code editor, locate the file, `heroes-list.component.html` and replace the placeholder content with the following HTML. +1. En tu editor de código, localiza el archivo `heroes-list.component.html` y reemplaza el contenido placeholder con el siguiente HTML. -1. In your code editor, open the file, `app.component.html` and replace its contents with the following HTML. +1. En tu editor de código, abre el archivo `app.component.html` y reemplaza su contenido con el siguiente HTML. -1. Verify that your new application runs as expected by running the `ng serve` command. +1. Verifica que tu nueva aplicación se ejecuta como se espera ejecutando el comando `ng serve`. ng serve -1. Open a browser to `http://localhost:4200`. +1. Abre un navegador en `http://localhost:4200`. - You should see a single web page, consisting of a title and the HTML of your two components. + Deberías ver una sola página web, consistiendo en un título y el HTML de tus dos componentes. -## Define your routes +## Definir tus rutas -In this section, you'll define two routes: +En esta sección, definirás dos rutas: -* The route `/crisis-center` opens the `crisis-center` component. -* The route `/heroes-list` opens the `heroes-list` component. +* La ruta `/crisis-center` abre el componente `crisis-center`. +* La ruta `/heroes-list` abre el componente `heroes-list`. -A route definition is a JavaScript object. -Each route typically has two properties. -The first property, `path`, is a string that specifies the URL path for the route. -The second property, `component`, is a string that specifies what component your application should display for that path. +Una definición de ruta es un objeto JavaScript. +Cada ruta típicamente tiene dos propiedades. +La primera propiedad, `path`, es un string que especifica la ruta de URL para la ruta. +La segunda propiedad, `component`, es un string que especifica qué componente debe mostrar tu aplicación para esa ruta. -1. From your code editor, create and open the `app.routes.ts` file. -1. Create and export a routes list for your application: +1. Desde tu editor de código, crea y abre el archivo `app.routes.ts`. +1. Crea y exporta una lista de rutas para tu aplicación: ```ts import {Routes} from '@angular/router'; @@ -94,182 +94,182 @@ The second property, `component`, is a string that specifies what component your export const routes = []; ``` -1. Add two routes for your first two components: +1. Agrega dos rutas para tus primeros dos componentes: ```ts {path: 'crisis-list', component: CrisisListComponent}, {path: 'heroes-list', component: HeroesListComponent}, ``` -This routes list is an array of JavaScript objects, with each object defining the properties of a route. +Esta lista de rutas es un array de objetos JavaScript, con cada objeto definiendo las propiedades de una ruta. -## Import `provideRouter` from `@angular/router` +## Importar `provideRouter` desde `@angular/router` -Routing lets you display specific views of your application depending on the URL path. -To add this functionality to your sample application, you need to update the `app.config.ts` file to use the router providers function, `provideRouter`. -You import this provider function from `@angular/router`. +El enrutamiento te permite mostrar vistas específicas de tu aplicación dependiendo de la ruta de URL. +Para agregar esta funcionalidad a tu aplicación de ejemplo, necesitas actualizar el archivo `app.config.ts` para usar la función de proveedores del router, `provideRouter`. +Importas esta función de proveedor desde `@angular/router`. -1. From your code editor, open the `app.config.ts` file. -1. Add the following import statements: +1. Desde tu editor de código, abre el archivo `app.config.ts`. +1. Agrega las siguientes declaraciones de importación: ```ts import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; ``` -1. Update the providers in the `appConfig`: +1. Actualiza los providers en el `appConfig`: ```ts providers: [provideRouter(routes)] ``` -For `NgModule` based applications, put the `provideRouter` in the `providers` list of the `AppModule`, or whichever module is passed to `bootstrapModule` in the application. +Para aplicaciones basadas en `NgModule`, coloca el `provideRouter` en la lista de `providers` del `AppModule`, o cualquier módulo que se pase a `bootstrapModule` en la aplicación. -## Update your component with `router-outlet` +## Actualizar tu componente con `router-outlet` -At this point, you have defined two routes for your application. -However, your application still has both the `crisis-list` and `heroes-list` components hard-coded in your `app.component.html` template. -For your routes to work, you need to update your template to dynamically load a component based on the URL path. +En este punto, has definido dos rutas para tu aplicación. +Sin embargo, tu aplicación aún tiene ambos componentes `crisis-list` y `heroes-list` codificados directamente en tu plantilla `app.component.html`. +Para que tus rutas funcionen, necesitas actualizar tu plantilla para cargar dinámicamente un componente basado en la ruta de URL. -To implement this functionality, you add the `router-outlet` directive to your template file. +Para implementar esta funcionalidad, agregas la directiva `router-outlet` a tu archivo de plantilla. -1. From your code editor, open the `app.component.html` file. -1. Delete the following lines. +1. Desde tu editor de código, abre el archivo `app.component.html`. +1. Elimina las siguientes líneas. -1. Add the `router-outlet` directive. +1. Agrega la directiva `router-outlet`. -1. Add `RouterOutlet` to the imports of the `AppComponent` in `app.component.ts` +1. Agrega `RouterOutlet` a los imports del `AppComponent` en `app.component.ts` ```ts imports: [RouterOutlet], ``` -View your updated application in your browser. -You should see only the application title. -To view the `crisis-list` component, add `crisis-list` to the end of the path in your browser's address bar. -For example: +Visualiza tu aplicación actualizada en tu navegador. +Solo deberías ver el título de la aplicación. +Para ver el componente `crisis-list`, agrega `crisis-list` al final de la ruta en la barra de direcciones de tu navegador. +Por ejemplo: http://localhost:4200/crisis-list -Notice that the `crisis-list` component displays. -Angular is using the route you defined to dynamically load the component. -You can load the `heroes-list` component the same way: +Nota que el componente `crisis-list` se muestra. +Angular está usando la ruta que definiste para cargar dinámicamente el componente. +Puedes cargar el componente `heroes-list` de la misma manera: http://localhost:4200/heroes-list -## Control navigation with UI elements +## Controlar la navegación con elementos UI -Currently, your application supports two routes. -However, the only way to use those routes is for the user to manually type the path in the browser's address bar. -In this section, you'll add two links that users can click to navigate between the `heroes-list` and `crisis-list` components. -You'll also add some CSS styles. -While these styles are not required, they make it easier to identify the link for the currently-displayed component. -You'll add that functionality in the next section. +Actualmente, tu aplicación soporta dos rutas. +Sin embargo, la única forma de usar esas rutas es que el usuario escriba manualmente la ruta en la barra de direcciones del navegador. +En esta sección, agregarás dos enlaces en los que los usuarios pueden hacer clic para navegar entre los componentes `heroes-list` y `crisis-list`. +También agregarás algunos estilos CSS. +Aunque estos estilos no son requeridos, facilitan identificar el enlace del componente actualmente mostrado. +Agregarás esa funcionalidad en la siguiente sección. -1. Open the `app.component.html` file and add the following HTML below the title. +1. Abre el archivo `app.component.html` y agrega el siguiente HTML debajo del título. - This HTML uses an Angular directive, `routerLink`. - This directive connects the routes you defined to your template files. + Este HTML usa una directiva de Angular, `routerLink`. + Esta directiva conecta las rutas que definiste a tus archivos de plantilla. -1. Add the `RouterLink` directive to the imports list of `AppComponent` in `app.component.ts`. +1. Agrega la directiva `RouterLink` a la lista de imports de `AppComponent` en `app.component.ts`. -1. Open the `app.component.css` file and add the following styles. +1. Abre el archivo `app.component.css` y agrega los siguientes estilos. -If you view your application in the browser, you should see these two links. -When you click on a link, the corresponding component appears. +Si visualizas tu aplicación en el navegador, deberías ver estos dos enlaces. +Cuando haces clic en un enlace, aparece el componente correspondiente. -## Identify the active route +## Identificar la ruta activa -While users can navigate your application using the links you added in the previous section, they don't have a straightforward way to identify what the active route is. -Add this functionality using Angular's `routerLinkActive` directive. +Aunque los usuarios pueden navegar tu aplicación usando los enlaces que agregaste en la sección anterior, no tienen una forma directa de identificar cuál es la ruta activa. +Agrega esta funcionalidad usando la directiva `routerLinkActive` de Angular. -1. From your code editor, open the `app.component.html` file. -1. Update the anchor tags to include the `routerLinkActive` directive. +1. Desde tu editor de código, abre el archivo `app.component.html`. +1. Actualiza las etiquetas anchor para incluir la directiva `routerLinkActive`. -1. Add the `RouterLinkActive` directive to the `imports` list of `AppComponent` in `app.component.ts`. +1. Agrega la directiva `RouterLinkActive` a la lista de `imports` de `AppComponent` en `app.component.ts`. -View your application again. -As you click one of the buttons, the style for that button updates automatically, identifying the active component to the user. -By adding the `routerLinkActive` directive, you inform your application to apply a specific CSS class to the active route. -In this tutorial, that CSS class is `activebutton`, but you could use any class that you want. +Visualiza tu aplicación nuevamente. +Al hacer clic en uno de los botones, el estilo para ese botón se actualiza automáticamente, identificando el componente activo para el usuario. +Al agregar la directiva `routerLinkActive`, informas a tu aplicación que aplique una clase CSS específica a la ruta activa. +En este tutorial, esa clase CSS es `activebutton`, pero podrías usar cualquier clase que desees. -Note that we are also specifying a value for the `routerLinkActive`'s `ariaCurrentWhenActive`. This makes sure that visually impaired users (which may not perceive the different styling being applied) can also identify the active button. For more information see the Accessibility Best Practices [Active links identification section](/best-practices/a11y#active-links-identification). +Nota que también estamos especificando un valor para el `ariaCurrentWhenActive` de `routerLinkActive`. Esto asegura que los usuarios con discapacidades visuales (que pueden no percibir el estilo diferente que se está aplicando) también puedan identificar el botón activo. Para más información consulta las Mejores Prácticas de Accesibilidad [sección de identificación de enlaces activos](/best-practices/a11y#active-links-identification). -## Adding a redirect +## Agregar una redirección -In this step of the tutorial, you add a route that redirects the user to display the `/heroes-list` component. +En este paso del tutorial, agregas una ruta que redirige al usuario para mostrar el componente `/heroes-list`. -1. From your code editor, open the `app.routes.ts` file. -1. Update the `routes` section as follows. +1. Desde tu editor de código, abre el archivo `app.routes.ts`. +1. Actualiza la sección `routes` como sigue. ```ts {path: '', redirectTo: '/heroes-list', pathMatch: 'full'}, ``` - Notice that this new route uses an empty string as its path. - In addition, it replaces the `component` property with two new ones: + Nota que esta nueva ruta usa un string vacío como su ruta. + Además, reemplaza la propiedad `component` con dos nuevas: - | Properties | Details | + | Propiedades | Detalles | |:--- |:--- | - | `redirectTo` | This property instructs Angular to redirect from an empty path to the `heroes-list` path. | - | `pathMatch` | This property instructs Angular on how much of the URL to match. For this tutorial, you should set this property to `full`. This strategy is recommended when you have an empty string for a path. For more information about this property, see the [Route API documentation](api/router/Route). | + | `redirectTo` | Esta propiedad instruye a Angular a redirigir desde una ruta vacía a la ruta `heroes-list`. | + | `pathMatch` | Esta propiedad instruye a Angular sobre cuánto de la URL debe coincidir. Para este tutorial, deberías establecer esta propiedad en `full`. Esta estrategia se recomienda cuando tienes un string vacío para una ruta. Para más información sobre esta propiedad, consulta la [documentación de la API Route](api/router/Route). | -Now when you open your application, it displays the `heroes-list` component by default. +Ahora cuando abres tu aplicación, muestra el componente `heroes-list` por defecto. -## Adding a 404 page +## Agregar una página 404 -It is possible for a user to try to access a route that you have not defined. -To account for this behavior, the best practice is to display a 404 page. -In this section, you'll create a 404 page and update your route configuration to show that page for any unspecified routes. +Es posible que un usuario intente acceder a una ruta que no has definido. +Para dar cuenta de este comportamiento, la mejor práctica es mostrar una página 404. +En esta sección, crearás una página 404 y actualizarás tu configuración de rutas para mostrar esa página para cualquier ruta no especificada. -1. From the terminal, create a new component, `PageNotFound`. +1. Desde la terminal, crea un nuevo componente, `PageNotFound`. ng generate component page-not-found -1. From your code editor, open the `page-not-found.component.html` file and replace its contents with the following HTML. +1. Desde tu editor de código, abre el archivo `page-not-found.component.html` y reemplaza su contenido con el siguiente HTML. -1. Open the `app.routes.ts` file and add the following route to the routes list: +1. Abre el archivo `app.routes.ts` y agrega la siguiente ruta a la lista de rutas: ```ts {path: '**', component: PageNotFoundComponent} ``` - The new route uses a path, `**`. - This path is how Angular identifies a wildcard route. - Any route that does not match an existing route in your configuration will use this route. + La nueva ruta usa una ruta, `**`. + Esta ruta es cómo Angular identifica una ruta comodín. + Cualquier ruta que no coincida con una ruta existente en tu configuración usará esta ruta. -IMPORTANT: Notice that the wildcard route is placed at the end of the array. -The order of your routes is important, as Angular applies routes in order and uses the first match it finds. +IMPORTANTE: Nota que la ruta comodín se coloca al final del array. +El orden de tus rutas es importante, ya que Angular aplica rutas en orden y usa la primera coincidencia que encuentra. -Try navigating to a non-existing route on your application, such as `http://localhost:4200/powers`. -This route doesn't match anything defined in your `app.routes.ts` file. -However, because you defined a wildcard route, the application automatically displays your `PageNotFound` component. +Intenta navegar a una ruta no existente en tu aplicación, como `http://localhost:4200/powers`. +Esta ruta no coincide con nada definido en tu archivo `app.routes.ts`. +Sin embargo, como definiste una ruta comodín, la aplicación automáticamente muestra tu componente `PageNotFound`. -## Next steps +## Próximos pasos -At this point, you have a basic application that uses Angular's routing feature to change what components the user can see based on the URL address. -You have extended these features to include a redirect, as well as a wildcard route to display a custom 404 page. +En este punto, tienes una aplicación básica que usa la característica de enrutamiento en Angular para cambiar qué componentes puede ver el usuario basándose en la dirección URL. +Has extendido estas características para incluir una redirección, así como una ruta comodín para mostrar una página 404 personalizada. -For more information about routing, see the following topics: +Para más información sobre enrutamiento, consulta los siguientes temas: - + diff --git a/adev-es/src/content/guide/routing/routing-with-urlmatcher.en.md b/adev-es/src/content/guide/routing/routing-with-urlmatcher.en.md new file mode 100644 index 0000000..2368c3f --- /dev/null +++ b/adev-es/src/content/guide/routing/routing-with-urlmatcher.en.md @@ -0,0 +1,116 @@ +# Creating custom route matches + +The Angular Router supports a powerful matching strategy that you can use to help users navigate your application. +This matching strategy supports static routes, variable routes with parameters, wildcard routes, and so on. +Also, build your own custom pattern matching for situations in which the URLs are more complicated. + +In this tutorial, you'll build a custom route matcher using Angular's `UrlMatcher`. +This matcher looks for a Twitter handle in the URL. + +## Objectives + +Implement Angular's `UrlMatcher` to create a custom route matcher. + +## Create a sample application + +Using the Angular CLI, create a new application, *angular-custom-route-match*. +In addition to the default Angular application framework, you will also create a *profile* component. + +1. Create a new Angular project, *angular-custom-route-match*. + + ```shell + ng new angular-custom-route-match + ``` + + When prompted with `Would you like to add Angular routing?`, select `Y`. + + When prompted with `Which stylesheet format would you like to use?`, select `CSS`. + + After a few moments, a new project, `angular-custom-route-match`, is ready. + +1. From your terminal, navigate to the `angular-custom-route-match` directory. +1. Create a component, *profile*. + + ```shell + ng generate component profile + ``` + +1. In your code editor, locate the file, `profile.component.html` and replace the placeholder content with the following HTML. + + + +1. In your code editor, locate the file, `app.component.html` and replace the placeholder content with the following HTML. + + + +## Configure your routes for your application + +With your application framework in place, you next need to add routing capabilities to the `app.config.ts` file. +As a part of this process, you will create a custom URL matcher that looks for a Twitter handle in the URL. +This handle is identified by a preceding `@` symbol. + +1. In your code editor, open your `app.config.ts` file. +1. Add an `import` statement for Angular's `provideRouter` and `withComponentInputBinding` as well as the application routes. + + ```ts + import {provideRouter, withComponentInputBinding} from '@angular/router'; + + import {routes} from './app.routes'; + ``` + +1. In the providers array, add a `provideRouter(routes, withComponentInputBinding())` statement. + +1. Define the custom route matcher by adding the following code to the application routes. + + + +This custom matcher is a function that performs the following tasks: + +* The matcher verifies that the array contains only one segment +* The matcher employs a regular expression to ensure that the format of the username is a match +* If there is a match, the function returns the entire URL, defining a `username` route parameter as a substring of the path +* If there isn't a match, the function returns null and the router continues to look for other routes that match the URL + +HELPFUL: A custom URL matcher behaves like any other route definition. Define child routes or lazy loaded routes as you would with any other route. + +## Reading the route parameters + +With the custom matcher in place, you can now bind the route parameter in the `profile` component. + +In your code editor, open your `profile.component.ts` file and create an `Input` matching the `username` parameter. +We added the `withComponentInputBinding` feature earlier +in `provideRouter`. This allows the `Router` to bind information directly to the route components. + +```ts +@Input() username!: string; +``` + +## Test your custom URL matcher + +With your code in place, you can now test your custom URL matcher. + +1. From a terminal window, run the `ng serve` command. + + + ng serve + + +1. Open a browser to `http://localhost:4200`. + + You should see a single web page, consisting of a sentence that reads `Navigate to my profile`. + +1. Click the **my profile** hyperlink. + + A new sentence, reading `Hello, Angular!` appears on the page. + +## Next steps + +Pattern matching with the Angular Router provides you with a lot of flexibility when you have dynamic URLs in your application. +To learn more about the Angular Router, see the following topics: + + + + + + +HELPFUL: This content is based on [Custom Route Matching with the Angular Router](https://medium.com/@brandontroberts/custom-route-matching-with-the-angular-router-fbdd48665483), by [Brandon Roberts](https://twitter.com/brandontroberts). diff --git a/adev-es/src/content/guide/routing/routing-with-urlmatcher.md b/adev-es/src/content/guide/routing/routing-with-urlmatcher.md index 2368c3f..055ba0d 100644 --- a/adev-es/src/content/guide/routing/routing-with-urlmatcher.md +++ b/adev-es/src/content/guide/routing/routing-with-urlmatcher.md @@ -1,56 +1,56 @@ -# Creating custom route matches +# Crear coincidencias de ruta personalizadas -The Angular Router supports a powerful matching strategy that you can use to help users navigate your application. -This matching strategy supports static routes, variable routes with parameters, wildcard routes, and so on. -Also, build your own custom pattern matching for situations in which the URLs are more complicated. +Angular Router soporta una estrategia de coincidencia poderosa que puedes usar para ayudar a los usuarios a navegar tu aplicación. +Esta estrategia de coincidencia soporta rutas estáticas, rutas variables con parámetros, rutas comodín, y más. +Además, puedes construir tu propia coincidencia de patrón personalizada para situaciones en las que las URLs son más complicadas. -In this tutorial, you'll build a custom route matcher using Angular's `UrlMatcher`. -This matcher looks for a Twitter handle in the URL. +En este tutorial, construirás un matcher de ruta personalizado usando `UrlMatcher` de Angular. +Este matcher busca un handle de Twitter en la URL. -## Objectives +## Objetivos -Implement Angular's `UrlMatcher` to create a custom route matcher. +Implementar `UrlMatcher` de Angular para crear un matcher de ruta personalizado. -## Create a sample application +## Crear una aplicación de ejemplo -Using the Angular CLI, create a new application, *angular-custom-route-match*. -In addition to the default Angular application framework, you will also create a *profile* component. +Usando Angular CLI, crea una nueva aplicación, *angular-custom-route-match*. +Además del framework de aplicación Angular predeterminado, también crearás un componente *profile*. -1. Create a new Angular project, *angular-custom-route-match*. +1. Crea un nuevo proyecto Angular, *angular-custom-route-match*. ```shell ng new angular-custom-route-match ``` - When prompted with `Would you like to add Angular routing?`, select `Y`. + Cuando se te pregunte `Would you like to add Angular routing?`, selecciona `Y`. - When prompted with `Which stylesheet format would you like to use?`, select `CSS`. + Cuando se te pregunte `Which stylesheet format would you like to use?`, selecciona `CSS`. - After a few moments, a new project, `angular-custom-route-match`, is ready. + Después de unos momentos, un nuevo proyecto, `angular-custom-route-match`, estará listo. -1. From your terminal, navigate to the `angular-custom-route-match` directory. -1. Create a component, *profile*. +1. Desde tu terminal, navega al directorio `angular-custom-route-match`. +1. Crea un componente, *profile*. ```shell ng generate component profile ``` -1. In your code editor, locate the file, `profile.component.html` and replace the placeholder content with the following HTML. +1. En tu editor de código, localiza el archivo `profile.component.html` y reemplaza el contenido placeholder con el siguiente HTML. -1. In your code editor, locate the file, `app.component.html` and replace the placeholder content with the following HTML. +1. En tu editor de código, localiza el archivo `app.component.html` y reemplaza el contenido placeholder con el siguiente HTML. -## Configure your routes for your application +## Configurar las rutas para tu aplicación -With your application framework in place, you next need to add routing capabilities to the `app.config.ts` file. -As a part of this process, you will create a custom URL matcher that looks for a Twitter handle in the URL. -This handle is identified by a preceding `@` symbol. +Con el framework de tu aplicación en su lugar, a continuación necesitas agregar capacidades de enrutamiento al archivo `app.config.ts`. +Como parte de este proceso, crearás un matcher de URL personalizado que busca un handle de Twitter en la URL. +Este handle se identifica por un símbolo `@` precedente. -1. In your code editor, open your `app.config.ts` file. -1. Add an `import` statement for Angular's `provideRouter` and `withComponentInputBinding` as well as the application routes. +1. En tu editor de código, abre tu archivo `app.config.ts`. +1. Agrega una declaración `import` para `provideRouter` y `withComponentInputBinding` de Angular, así como las rutas de la aplicación. ```ts import {provideRouter, withComponentInputBinding} from '@angular/router'; @@ -58,59 +58,59 @@ This handle is identified by a preceding `@` symbol. import {routes} from './app.routes'; ``` -1. In the providers array, add a `provideRouter(routes, withComponentInputBinding())` statement. +1. En el array de providers, agrega una declaración `provideRouter(routes, withComponentInputBinding())`. -1. Define the custom route matcher by adding the following code to the application routes. +1. Define el matcher de ruta personalizado agregando el siguiente código a las rutas de la aplicación. -This custom matcher is a function that performs the following tasks: +Este matcher personalizado es una función que realiza las siguientes tareas: -* The matcher verifies that the array contains only one segment -* The matcher employs a regular expression to ensure that the format of the username is a match -* If there is a match, the function returns the entire URL, defining a `username` route parameter as a substring of the path -* If there isn't a match, the function returns null and the router continues to look for other routes that match the URL +* El matcher verifica que el array contiene solo un segmento +* El matcher emplea una expresión regular para asegurar que el formato del nombre de usuario coincida +* Si hay una coincidencia, la función retorna la URL completa, definiendo un parámetro de ruta `username` como una subcadena de la ruta +* Si no hay coincidencia, la función retorna null y el router continúa buscando otras rutas que coincidan con la URL -HELPFUL: A custom URL matcher behaves like any other route definition. Define child routes or lazy loaded routes as you would with any other route. +ÚTIL: Un matcher de URL personalizado se comporta como cualquier otra definición de ruta. Define rutas hijo o rutas con lazy loading como lo harías con cualquier otra ruta. -## Reading the route parameters +## Leer los parámetros de ruta -With the custom matcher in place, you can now bind the route parameter in the `profile` component. +Con el matcher personalizado en su lugar, ahora puedes vincular el parámetro de ruta en el componente `profile`. -In your code editor, open your `profile.component.ts` file and create an `Input` matching the `username` parameter. -We added the `withComponentInputBinding` feature earlier -in `provideRouter`. This allows the `Router` to bind information directly to the route components. +En tu editor de código, abre tu archivo `profile.component.ts` y crea un `Input` que coincida con el parámetro `username`. +Agregamos la característica `withComponentInputBinding` anteriormente +en `provideRouter`. Esto permite que el `Router` vincule información directamente a los componentes de ruta. ```ts @Input() username!: string; ``` -## Test your custom URL matcher +## Probar tu matcher de URL personalizado -With your code in place, you can now test your custom URL matcher. +Con tu código en su lugar, ahora puedes probar tu matcher de URL personalizado. -1. From a terminal window, run the `ng serve` command. +1. Desde una ventana de terminal, ejecuta el comando `ng serve`. ng serve -1. Open a browser to `http://localhost:4200`. +1. Abre un navegador en `http://localhost:4200`. - You should see a single web page, consisting of a sentence that reads `Navigate to my profile`. + Deberías ver una sola página web, consistiendo en una oración que dice `Navigate to my profile`. -1. Click the **my profile** hyperlink. +1. Haz clic en el hipervínculo **my profile**. - A new sentence, reading `Hello, Angular!` appears on the page. + Una nueva oración, que dice `Hello, Angular!` aparece en la página. -## Next steps +## Próximos pasos -Pattern matching with the Angular Router provides you with a lot of flexibility when you have dynamic URLs in your application. -To learn more about the Angular Router, see the following topics: +La coincidencia de patrones con Angular Router te proporciona mucha flexibilidad cuando tienes URLs dinámicas en tu aplicación. +Para aprender más sobre Angular Router, consulta los siguientes temas: - + -HELPFUL: This content is based on [Custom Route Matching with the Angular Router](https://medium.com/@brandontroberts/custom-route-matching-with-the-angular-router-fbdd48665483), by [Brandon Roberts](https://twitter.com/brandontroberts). +ÚTIL: Este contenido está basado en [Custom Route Matching with the Angular Router](https://medium.com/@brandontroberts/custom-route-matching-with-the-angular-router-fbdd48665483), de [Brandon Roberts](https://twitter.com/brandontroberts). diff --git a/adev-es/src/content/guide/routing/show-routes-with-outlets.en.md b/adev-es/src/content/guide/routing/show-routes-with-outlets.en.md new file mode 100644 index 0000000..3b82895 --- /dev/null +++ b/adev-es/src/content/guide/routing/show-routes-with-outlets.en.md @@ -0,0 +1,170 @@ +# Show routes with outlets + +The `RouterOutlet` directive is a placeholder that marks the location where the router should render the component for the current URL. + +```angular-html + + + +``` + +```angular-ts +import { Component } from '@angular/core'; +import { RouterOutlet } from '@angular/router'; + +@Component({ + selector: 'app-root', + imports: [RouterOutlet], + templateUrl: './app.component.html', + styleUrl: './app.component.css' +}) +export class AppComponent {} +``` + +In this example, if an application has the following routes defined: + +```angular-ts +import { Routes } from '@angular/router'; +import { HomeComponent } from './home/home.component'; +import { ProductsComponent } from './products/products.component'; + +const routes: Routes = [ + { + path: '', + component: HomeComponent, + title: 'Home Page' + }, + { + path: 'products', + component: ProductsComponent, + title: 'Our Products' + } +]; +``` + +When a user visits `/products`, Angular renders the following: + +```angular-html + + + +``` + +If the user goes back to the home page, then Angular renders: + +```angular-html + + + +``` + +When displaying a route, the `` element remains present in the DOM as a reference point for future navigations. Angular inserts routed content just after the outlet element as a sibling. + +```angular-html + + + + +``` + +```angular-html + +... + +... +... +``` + +## Nesting routes with child routes + +As your application grows more complex, you might want to create routes that are relative to a component other than your root component. This enables you to create experiences where only part of the application changes when the URL changes, as opposed to the users feeling like the entire page is refreshed. + +These types of nested routes are called child routes. This means you're adding a second `` to your app, because it is in addition to the `` in AppComponent. + +In this example, the `Settings` component will display the desired panel based on what the user selects. One of the unique things you'll notice about child routes is that the component often has its own `