Part 10 - ngrx selectors
Lets add a main menu to our customer portal to show the name of the logged in user.
Add a new layout lib to a customer-portal directory
ng g lib layout --directory=customer-portal
2. Add a layout container component
ng g c containers/layout -a=customer-portal/layout
3. Add Material and Router module
libs/customer-portal/layout/src/layout.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MaterialModule } from '@demo-app/material';
import { LayoutComponent } from './containers/layout/layout.component';
import { RouterModule } from '@angular/router';
const COMPONENTS = [LayoutComponent];
@NgModule({
imports: [CommonModule, MaterialModule, RouterModule],
declarations: [COMPONENTS],
exports: [COMPONENTS]
})
export class LayoutModule {
}
3. Add a material toolbar
libs/customer-portal/layout/src/containers/layout/layout.component.html
<mat-toolbar color="primary" fxLayout="row">
<span>Customer Portal</span>
<div class="right-nav">
<span>{{(user$ | async)?.username}}</span>
</div>
</mat-toolbar>
<ng-content></ng-content>
- Add styles to styles.scss
apps/customer-portal/src/styles.scss
@import '~@angular/material/prebuilt-themes/deeppurple-amber.css';
body {
margin: 0;
}
libs/customer-portal/layout/src/containers/layout/layout.component.scss
.right-nav {
margin-left: auto;
}
4. Update layout component to select user from the store
libs/customer-portal/layout/src/containers/layout/layout.component.ts
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { AuthState } from '@demo-app/auth';
import { User } from '@demo-app/data-models';
import { Observable } from 'rxjs/Observable';
@Component({
selector: 'app-layout',
templateUrl: './layout.component.html',
styleUrls: ['./layout.component.scss']
})
export class LayoutComponent implements OnInit {
user$: Observable<User>;
constructor(private store: Store<AuthState>) { }
ngOnInit() {
this.user$ = this.store.select(state => state.auth.user);
}
}
- Add layout module to the customer-portal app
apps/customer-portal/src/app/app.module.ts
import { LayoutModule } from '@demo-app/customer-portal/layout';
@NgModule({
imports: [
...
LayoutModule
...
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
- Add the layout component to the main app.component.html
apps/customer-portal/src/app/app.component.html
<app-layout>
<router-outlet></router-outlet>
</app-layout>
5. Add selector file
- Add a file called index.ts to the +state folder of your auth state lib
libs/auth/src/+state/index.ts
import { createSelector, createFeatureSelector } from '@ngrx/store';
import { Auth } from './auth.interfaces';
export const getAuthState = createFeatureSelector<Auth>('auth');
export const getUser = createSelector(getAuthState, state => state.user);
- Ensure you have re-exported your publically available paths in the auth libs index.ts file
libs/auth/index.ts
export { AuthModule , authRoutes } from './src/auth.module';
export { AuthGuard } from './src/guards/auth.guard';
export { AuthState } from './src/+state/auth.interfaces';
export * from './src/+state';
6. Use selector in Layout component
libs/customer-portal/layout/src/containers/layout/layout.component.ts
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { AuthState, getUser } from '@demo-app/auth';
import { User } from '@demo-app/data-models';
import { Observable } from 'rxjs/Observable';
@Component({
selector: 'app-layout',
templateUrl: './layout.component.html',
styleUrls: ['./layout.component.scss']
})
export class LayoutComponent implements OnInit {
user$: Observable<User>;
constructor(private store: Store<AuthState>) { }
ngOnInit() {
this.user$ = this.store.select(getUser);
}
}