Using Selectors page
Learn how to use NgRx Selectors in a Component to access data from a store.
Quick Start: You can checkout this branch to get your codebase ready to work on this section.
Overview
Update
DashboardComponent
’susername$
anduserId$
members to use Login Selectors.Update
AuthenticationGuard
’scanActivate()
method to use Login Selector.
Problem 1: Update username$
and userId$
to use Login Selectors on DashboardComponent
DashboardComponent
should use the LoginSelectors.selectUsername
and LoginSelectors.selectUserId
Selectors for its username$
and userId$
members.
P1: What you need to know
Now that we have our Selectors defined, we can inject Store
into our Components
and use the select()
method to obtain slices of state using our Selectors:
// Note: This example code is not part of our application repo or solution
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import * as ContactSelectors from '../store/contact/contact.selectors';
@Component({
selector: 'app-contact',
templateUrl: './contact.component.html',
styleUrls: ['./contact.component.scss'],
})
export class ContactComponent {
readonly emailAddress$ = this.store.select(ContactSelectors.emailAddress);
constructor(private store: Store) {}
}
In the DashboardComponent
, there is are TODO
’s where the Login Selectors should be used.
P1: Solution
src/app/dashboard/dashboard.component.ts
// src/app/dashboard/dashboard.component.ts
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import * as LoginActions from '../store/login/login.actions';
import * as LoginSelectors from '../store/login/login.selectors';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss'],
})
export class DashboardComponent {
// Select username from store
readonly username$ = this.store.select(LoginSelectors.selectUsername);
// Select user ID from store
readonly userId$ = this.store.select(LoginSelectors.selectUserId);
constructor(private store: Store) {}
logout(): void {
this.store.dispatch(LoginActions.logout());
}
}
Problem 2: Update canActivate()
to use Login Selector on AuthenticationGuard
AuthenticationGuard
’s canActivate()
method should use the LoginSelectors.selectToken
Selector.
P2: What you need to know
In the AuthenticationGuard
, there is a TODO
where the Login Selector should be used.
P2: Solution
src/app/guards/authentication.guard.ts
// src/app/guards/authentication.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, CanLoad, Router, UrlTree } from '@angular/router';
import { Store } from '@ngrx/store';
import { map, Observable } from 'rxjs';
import * as LoginSelectors from '../store/login/login.selectors';
@Injectable({
providedIn: 'root'
})
export class AuthenticationGuard implements CanActivate, CanLoad {
constructor(private router: Router, private store: Store) {}
canActivate(): Observable<UrlTree | boolean> {
return this.store.select(LoginSelectors.selectToken).pipe(
map(token => {
// Allow navigation since there is a login token
if (token) {
return true;
}
// Redirect back to login page
return this.router.createUrlTree(['']);
})
);
}
canLoad(): Observable<UrlTree | boolean> {
return this.canActivate();
}
}
Wrap-up: By the end of this section, your code should match this branch. You can also compare the code changes for our solution to this section on GitHub or you can use the following command in your terminal:
git diff origin/use-selectors