Reputation: 63
We have a User
component that receives a user object as an @input
:
export class UserComponent implements OnInit {
@Input() user: User;
constructor() {}
}
Here the corresponding template:
<div class="user-box">
<img class="avatar" [src]="user.avatar" alt="user_picture">
<div class="infos">
<div class="username">{{ user.username }}</div>
<div>{{ user.email }}</div>
<div class="gender">{{ user.gender }}</div>
</div>
</div>
In a route component UsersList
(primary <router-outlet>
) we need to display a list of users to the screen:
<user
*ngFor="let user of users
[user]="user"
(click)="selectUser(user)">
</user>
Then, when we click to select a user from the list, we show the selected user data using the same User
component but this time as a route component (named <router-outlet name="selected">
):
Here our routes:
const ROUTES: Routes = [
{
path: '',
component: UsersList
},
{
path: ':username',
component: UserComponent,
outlet: 'selected'
}
];
So, here the selectUser()
function:
selectUser(user: User) {
return this.router.navigate([ { outlets: { selected: [ user.username ] } } ], { state: { user } });
}
And inside our User
component, we need to implement the OnInit
interface:
if (this.route.outlet === 'selected') {
this.route.paramMap.pipe(map(() => window.history.state)).subscribe(state => {
if (!state.user) {
return this.router.navigate([ { outlets: { selected: null } } ]);
}
this.user = state.user;
});
}
All of this works perfectly fine! What I am wondering though is if it's a good practice to do it this way?
FYI, I have also tried to use a route resolver but I can't have access to the NavigationExtras
state
object... The only way to get the user data inside a resolver is to pass it as queryParams
. It can be fine when we have 3 properties, but, if we have 10+ properties, the URL becomes ugly and messy. And also, it seems that a resolver role is to resolve asynchronous data and not passing static data.
Thanks for giving your insights!
Upvotes: 1
Views: 2658
Reputation: 2086
The good practice, or let's say "the Angular way", is to use route resolvers how is written in the documentation: https://angular.io/guide/router#fetch-data-before-navigating.
I use resolvers when I can, so I can write clean page components that get the data they need from the router as they are instantiated (I can also re-use the resolver for other routes, but that rarely happens).
This makes also the routes independent from each other: I can see the user page before going into the user list page, I don't think I can do that with your current code. Plus, if the user does not exist, I could redirect to the 404 page from the resolver directly.
By the way, resolvers could have some drawbacks to keep in mind:
Upvotes: 1