Cuando empezamos un proyecto en Angular, lo primero que buscamos es organización, escalabilidad y claridad en las rutas. Aunque las rutas principales suelen ser sencillas de configurar, la verdadera magia aparece cuando entramos en el mundo de las rutas hijas en Angular. Estas nos permiten crear aplicaciones modulares, reutilizables y mucho más fáciles de mantener en el tiempo.
A lo largo de este artículo vamos a repasar cómo funcionan, cómo implementarlas, cómo integrarlas con Tailwind y DaisyUI y, sobre todo, cómo aplicar buenas prácticas para que tu aplicación sea un proyecto robusto y ordenado.
Introducción: una idea de aplicación en Angular
Imagina que quieres crear una aplicación que muestre información de distintos países. Tendrás secciones como “Búsqueda”, “Detalle” y “Favoritos”. Cada sección podría ser un módulo separado, con sus propios componentes y rutas internas. En este escenario, las rutas hijas en Angular son clave para estructurar todo el flujo de la app.
Este tipo de ejemplos son muy prácticos porque reflejan la importancia de dividir una aplicación en features independientes, algo que nos ayuda a mantener el control del proyecto sin volvernos locos con un archivo de rutas gigante.
Estructura inicial de una aplicación con rutas hijas en Angular
Cuando montamos un proyecto con Angular que va a crecer, lo mejor es planear desde el principio la estructura de carpetas. Una organización típica para una app con rutas hijas podría ser:
src/
└── app/
├── core/ # servicios generales, interceptores
├── shared/ # componentes y módulos compartidos
├── countries/ # módulo de países (feature)
│ ├── components/
│ │ ├── country-list/
│ │ ├── country-detail/
│ │ └── search-input/
│ ├── countries-routing.module.ts
│ └── countries.module.ts
├── app-routing.module.ts
└── app.module.ts
Con este enfoque, cada feature module tiene sus propios componentes y su archivo de rutas, lo que facilita usar rutas hijas en Angular sin ensuciar el app-routing.module.ts
.
Configuración inicial del proyecto
Antes de lanzarnos con las rutas hijas, lo primero es crear la base de nuestro proyecto en Angular. Para ello:
- Instala Angular CLI si aún no lo tienes:
npm install -g @angular/cli
- Crea un nuevo proyecto:
ng new angular-app
- Elige routing durante la configuración y selecciona SCSS o el preprocesador de tu preferencia.
En este punto, ya tendrás el esqueleto de tu aplicación listo para empezar a trabajar con módulos y rutas. Si quieres ver otro ejemplo sencillo de configuración y uso práctico, puedes revisar esta guía de Calculadora de IMC con Angular y TypeScript.
Uso de Tailwind y DaisyUI en Angular
Hoy en día no basta con que una aplicación funcione: también debe verse bien. Y aquí es donde TailwindCSS y DaisyUI entran en juego.
- Tailwind nos da utilidades rápidas para estilos, sin tener que pelear con hojas de CSS gigantes.
- DaisyUI, por su parte, añade componentes ya diseñados, lo que acelera aún más el desarrollo.
La integración en Angular es sencilla:
- Instala Tailwind:
npm install -D tailwindcss postcss autoprefixer npx tailwindcss init
- Configura el archivo
tailwind.config.js
. - Instala DaisyUI:
npm install daisyui
- Actívalo en
tailwind.config.js
:module.exports = { plugins: [require('daisyui')], }
Con esto ya puedes usar clases utilitarias y componentes predefinidos en tus vistas de Angular..
Creación y comunicación entre componentes en rutas hijas de Angular
Un proyecto en Angular se construye con componentes. La comunicación entre componentes es esencial para que la información fluya correctamente.
Existen varias formas de comunicación:
- @Input() → permite pasar datos del padre al hijo.
- @Output() → se usa para emitir eventos desde el hijo al padre.
- Servicios compartidos → útiles cuando la comunicación debe existir entre componentes no relacionados directamente.
Por ejemplo, supongamos un componente de búsqueda:
@Component({
selector: "country-search-input",
template: `
<input
type="text"
[placeholder]="placeholder"
(input)="onInput($event)"
class="input input-bordered w-full max-w-xs"
/>
`
})
export class SearchInputComponent {
@Input() placeholder: string = 'Buscar país...';
@Output() value = new EventEmitter<string>();
onInput(event: any) {
this.value.emit(event.target.value);
}
}
Luego, en el componente padre (CountriesComponent
), podemos capturar el evento:
<country-search-input
[placeholder]="'Escribe un país...'"
(value)="onSearch($event)">
</country-search-input>
<country-list [filter]="searchTerm"></country-list>
Y en el .ts
:
export class CountriesComponent {
searchTerm: string = '';
onSearch(term: string) {
this.searchTerm = term;
}
}
Con este patrón, la búsqueda se propaga hacia el listado de países filtrando en tiempo real.
Configuración de rutas hijas en Angular paso a paso
Una configuración típica de rutas hijas en Angular dentro de countries-routing.module.ts
quedaría así:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CountriesComponent } from './components/countries.component';
import { CountryListComponent } from './components/country-list/country-list.component';
import { CountryDetailComponent } from './components/country-detail/country-detail.component';
import { SearchInputComponent } from './components/search-input/search-input.component';
const routes: Routes = [
{
path: '',
component: CountriesComponent,
children: [
{ path: 'list', component: CountryListComponent },
{ path: 'search', component: SearchInputComponent },
{ path: 'detail/:id', component: CountryDetailComponent }
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class CountriesRoutingModule {}
Aquí, CountriesComponent
actúa como contenedor y las rutas hijas (list
, search
, detail/:id
) renderizan distintos componentes dentro de él.
Si quieres ir más allá en el tema de rutas, puedes revisar también este artículo sobre Angular avanzado: rutas dinámicas y señales, donde se ven casos aún más potentes.
Separación de rutas por módulo o feature
Uno de los mayores problemas al trabajar con Angular es que el archivo de rutas principal puede crecer demasiado. Para evitarlo, lo mejor es crear un archivo de rutas por cada módulo.
Ejemplo de un módulo con su propia configuración:
const routes: Routes = [
{ path: '', component: CountriesListComponent },
{ path: 'detail/:id', component: CountryDetailComponent }
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class CountriesRoutingModule {}
Este enfoque hace que cada módulo sea independiente y más fácil de mantener.
Implementación de carga perezosa (lazy loading) con rutas hijas en Angular
El lazy loading es otra de esas joyas que Angular nos ofrece. Básicamente, consiste en cargar un módulo solo cuando se necesita, en lugar de hacerlo todo de golpe.
Esto mejora el rendimiento y reduce el tiempo de carga inicial de la aplicación.
Ejemplo:
const routes: Routes = [
{
path: 'countries',
loadChildren: () =>
import('./countries/countries.module').then(m => m.CountriesModule)
}
];
Con este patrón, Angular carga el módulo solo cuando el usuario accede a esa ruta.
Ejemplo práctico con SearchInputComponent
Volvamos a nuestro componente de búsqueda:
@Component({
selector: "country-search-input",
templateUrl: './search-input.component.html',
})
export class SearchInputComponent {
placeholder = input('Buscar');
value = output<string>();
}
Podemos integrarlo en el módulo de “Countries” como ruta hija. El flujo sería:
- El usuario accede a
/countries/search
. - Angular carga el módulo de países de forma perezosa.
- Dentro del módulo, se renderiza el componente de búsqueda.
- El valor introducido se emite hacia un componente padre encargado de mostrar los resultados.
De esta forma, el ciclo de búsqueda queda modularizado y optimizado.
Ejemplo de rutas anidadas en Angular
Podemos ir más allá creando rutas anidadas que usen outlets secundarios. Ejemplo:
const routes: Routes = [
{
path: 'countries',
component: CountriesComponent,
children: [
{ path: 'list', component: CountryListComponent },
{
path: 'detail/:id',
component: CountryDetailComponent,
children: [
{ path: 'map', component: CountryMapComponent },
{ path: 'stats', component: CountryStatsComponent }
]
}
]
}
];
Esto permite que el detalle de un país tenga sus propias subrutas internas (mapa, estadísticas, etc.).
Buenas prácticas al trabajar con rutas en Angular
- Usa módulos separados para cada feature.
- Define rutas hijas solo cuando realmente exista jerarquía de vistas.
- Implementa lazy loading para reducir el peso inicial de la app.
- No olvides usar guardas (
canActivate
,canLoad
) si ciertas rutas requieren autenticación. - Combina Tailwind y DaisyUI para maquetar componentes de forma rápida y uniforme.
Para reforzar estas ideas, te recomiendo darle un vistazo a esta guía práctica sobre rutas dinámicas en Angular, donde se profundiza aún más en casos reales.
Conclusión: dominar rutas hijas en Angular
Las rutas hijas en Angular son mucho más que un detalle técnico: son la clave para crear aplicaciones escalables y fáciles de mantener. Junto con la comunicación entre componentes, la separación por módulos, el uso de lazy loading y la integración de frameworks como Tailwind y DaisyUI, tu aplicación puede crecer sin perder organización.
Si te interesa seguir ampliando tus conocimientos, Angular tiene un mundo de posibilidades: desde directivas avanzadas hasta optimización con señales y caché. Lo importante es que te acostumbres a pensar en módulos, componentes y rutas bien estructuradas, porque ese es el verdadero secreto para dominar este framework.
Para quienes quieran profundizar en otros enfoques, recomiendo explorar documentación oficial, pero también artículos prácticos de la comunidad como esta referencia sobre lazy loading en Angular (Angular Docs), que te servirá como guía avanzada.
Y si buscas ejemplos aplicados con código paso a paso, puedes repasar la Calculadora de IMC con Angular y TypeScript, que es otro proyecto práctico para afianzar conocimientos.