Skip to content

Commit

Permalink
feat(example): add examples of effects not based on the Actions stream
Browse files Browse the repository at this point in the history
As suggested, added two examples of effects not based on Actions stream:
- listen for router navigation events and update page title
- log out the user after a specified period of inactivity

Closes #1830
  • Loading branch information
Adrian Fâciu committed May 8, 2019
1 parent eec9cc6 commit 199a37e
Showing 10 changed files with 94 additions and 8 deletions.
6 changes: 5 additions & 1 deletion projects/example-app/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
@@ -10,7 +10,11 @@ export const routes: Routes = [
loadChildren: '@example-app/books/books.module#BooksModule',
canActivate: [AuthGuard],
},
{ path: '**', component: NotFoundPageComponent },
{
path: '**',
component: NotFoundPageComponent,
data: { title: 'Not found' },
},
];

@NgModule({
3 changes: 2 additions & 1 deletion projects/example-app/src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ import { ROOT_REDUCERS, metaReducers } from '@example-app/reducers';

import { AppComponent } from '@example-app/core/containers/app.component';
import { AppRoutingModule } from '@example-app/app-routing.module';
import { UserEffects, RouterEffects } from '@example-app/core/effects';

@NgModule({
imports: [
@@ -69,7 +70,7 @@ import { AppRoutingModule } from '@example-app/app-routing.module';
*
* See: https://ngrx.io/guide/effects#registering-root-effects
*/
EffectsModule.forRoot([]),
EffectsModule.forRoot([UserEffects, RouterEffects]),

CoreModule,
],
4 changes: 3 additions & 1 deletion projects/example-app/src/app/auth/auth-routing.module.ts
Original file line number Diff line number Diff line change
@@ -2,7 +2,9 @@ import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LoginPageComponent } from '@example-app/auth/containers';

const routes: Routes = [{ path: 'login', component: LoginPageComponent }];
const routes: Routes = [
{ path: 'login', component: LoginPageComponent, data: { title: 'Login' } },
];

@NgModule({
imports: [RouterModule.forChild(routes)],
15 changes: 13 additions & 2 deletions projects/example-app/src/app/auth/effects/auth.effects.ts
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ import {
import { Credentials } from '@example-app/auth/models';
import { AuthService } from '@example-app/auth/services';
import { LogoutConfirmationDialogComponent } from '@example-app/auth/components';
import { UserActions } from '@example-app/core/actions';

@Injectable()
export class AuthEffects {
@@ -60,12 +61,22 @@ export class AuthEffects {

return dialogRef.afterClosed();
}),
map(result =>
result ? AuthActions.logout() : AuthActions.logoutConfirmationDismiss()
map(
result =>
result
? AuthActions.logout()
: AuthActions.logoutConfirmationDismiss()
)
)
);

logoutIdleUser$ = createEffect(() =>
this.actions$.pipe(
ofType(UserActions.idle),
map(() => AuthActions.logout())
)
);

constructor(
private actions$: Actions,
private authService: AuthService,
13 changes: 11 additions & 2 deletions projects/example-app/src/app/books/books-routing.module.ts
Original file line number Diff line number Diff line change
@@ -6,13 +6,22 @@ import { CollectionPageComponent } from '@example-app/books/containers/collectio
import { BookExistsGuard } from '@example-app/books/guards/book-exists.guard';

export const routes: Routes = [
{ path: 'find', component: FindBookPageComponent },
{
path: 'find',
component: FindBookPageComponent,
data: { title: 'Find book' },
},
{
path: ':id',
component: ViewBookPageComponent,
canActivate: [BookExistsGuard],
data: { title: 'Book details' },
},
{
path: '',
component: CollectionPageComponent,
data: { title: 'Collection' },
},
{ path: '', component: CollectionPageComponent },
];

@NgModule({
3 changes: 2 additions & 1 deletion projects/example-app/src/app/core/actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as LayoutActions from './layout.actions';
import * as UserActions from './user.actions';

export { LayoutActions };
export { LayoutActions, UserActions };
3 changes: 3 additions & 0 deletions projects/example-app/src/app/core/actions/user.actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createAction } from '@ngrx/store';

export const idle = createAction('[User] Idle');
2 changes: 2 additions & 0 deletions projects/example-app/src/app/core/effects/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './user.effects';
export * from './router.effects';
32 changes: 32 additions & 0 deletions projects/example-app/src/app/core/effects/router.effects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Injectable } from '@angular/core';
import { createEffect } from '@ngrx/effects';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { Title } from '@angular/platform-browser';
import { tap, filter, map, mergeMap } from 'rxjs/operators';

@Injectable()
export class RouterEffects {
updateTitle$ = createEffect(
() =>
this.router.events.pipe(
filter(event => event instanceof NavigationEnd),
map(() => this.activatedRoute),
map(route => {
while (route.firstChild) route = route.firstChild;
return route;
}),
mergeMap(route => route.data),
map(data => data['title']),
tap(title => this.titleService.setTitle(title))
),
{
dispatch: false,
}
);

constructor(
private router: Router,
private titleService: Title,
private activatedRoute: ActivatedRoute
) {}
}
21 changes: 21 additions & 0 deletions projects/example-app/src/app/core/effects/user.effects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Injectable } from '@angular/core';
import { createEffect } from '@ngrx/effects';

import { fromEvent, merge, timer } from 'rxjs';
import { map, switchMapTo } from 'rxjs/operators';

import { UserActions } from '@example-app/core/actions';

@Injectable()
export class UserEffects {
clicks$ = fromEvent(document, 'click');
keys$ = fromEvent(document, 'keydown');
mouse$ = fromEvent(document, 'mousemove');

idle$ = createEffect(() =>
merge(this.clicks$, this.keys$, this.mouse$).pipe(
switchMapTo(timer(60 * 1000)),
map(() => UserActions.idle())
)
);
}

0 comments on commit 199a37e

Please sign in to comment.