Skip to content

Commit 98e7040

Browse files
author
Pietro Grandi
committed
composing reducers
1 parent e7bcd24 commit 98e7040

File tree

6 files changed

+130
-12
lines changed

6 files changed

+130
-12
lines changed

app/app.component.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
import {Component, OnInit} from '@angular/core';
22
import {SearchBox} from "./components/search-box/search-box.component";
3-
import {CurrentSearch, searchReducer} from "./components/youtube-search/search.reducer";
4-
import {Store, provideStore} from "@ngrx/store";
3+
import {CurrentSearch, searchReducer} from "./components/reducers/search.reducer";
4+
import {Store, provideStore, combineReducers} from "@ngrx/store";
55
import {Observable} from "rxjs/Rx";
6+
import {locationReducer} from "./components/reducers/location.reducer";
7+
import {ProximitySelector} from "./components/location/proximity-selector.component";
8+
9+
const mainReducer = combineReducers({
10+
searchByName: searchReducer,
11+
searchByLocation: locationReducer
12+
});
613

714
@Component({
815
selector: 'my-app',
916
providers: [
10-
provideStore({ currentSearch: searchReducer })
17+
provideStore({ currentSearch: mainReducer })
1118
],
12-
directives: [ SearchBox ],
19+
directives: [ SearchBox, ProximitySelector ],
1320
template: `
1421
<h1>{{title}}</h1>
1522
<div class="row">
1623
<search-box [store]="store"></search-box>
24+
<proximity-selector [store]="store"></proximity-selector>
1725
</div>
1826
<div class="row">
1927
<courses-list [searchResults]="results"></courses-list>
@@ -27,13 +35,13 @@ export class AppComponent implements OnInit {
2735
title = 'One Source of Truth for Angular 2';
2836

2937
private currentSearch: Observable<CurrentSearch>;
30-
38+
3139
constructor(
3240
private store: Store<CurrentSearch>
3341
) {
3442
this.currentSearch = this.store.select<CurrentSearch>('currentSearch');
3543
}
36-
44+
3745
ngOnInit() {
3846
this.currentSearch.subscribe((state: CurrentSearch) => {
3947
console.log(state);
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import {Component, EventEmitter, Input} from "@angular/core";
2+
import {Store} from "@ngrx/store";
3+
4+
@Component({
5+
selector: 'proximity-selector',
6+
inputs: ['store'],
7+
template: `
8+
<div class="input-group">
9+
<label for="useLocation">Use current location</label>
10+
<input type="checkbox"
11+
[disabled]="disabled"
12+
(change)="turnOnOffLocation($event)">
13+
</div>
14+
<div class="input-group">
15+
<label for="locationRadius">Radius</label>
16+
<input type="range" min="1" max="100" value="{{defaultRadius}}"
17+
(change)="onRadius($event)">
18+
</div>
19+
`
20+
})
21+
22+
export class ProximitySelector {
23+
24+
static StoreEvents = {
25+
position: 'ProximitySelector:POSITION',
26+
radius: 'ProximitySelector:RADIUS',
27+
off: 'ProximitySelector:OFF'
28+
};
29+
30+
@Input()
31+
store: Store<any>;
32+
33+
active = false;
34+
35+
defaultRadius = 50;
36+
37+
turnOnOffLocation($event: any) {
38+
this.active = $event.target.checked;
39+
if (this.active) {
40+
navigator.geolocation.getCurrentPosition((position: any) => {
41+
this.store.dispatch({
42+
type: ProximitySelector.StoreEvents.position,
43+
payload: {
44+
position: {
45+
latitude: position.coords.latitude,
46+
longitude: position.coords.longitude
47+
}
48+
}
49+
});
50+
});
51+
} else {
52+
this.store.dispatch({
53+
type: ProximitySelector.StoreEvents.off,
54+
payload: {}
55+
});
56+
}
57+
}
58+
59+
onRadius($event: any) {
60+
const radius = parseInt($event.target.value, 10);
61+
this.store.dispatch({
62+
type: ProximitySelector.StoreEvents.radius,
63+
payload: {
64+
radius: radius
65+
}
66+
});
67+
}
68+
69+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
export interface CurrentSearch {
3+
text: string,
4+
position: {
5+
latitude: number,
6+
longitude: number
7+
},
8+
radius: number
9+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { ActionReducer, Action } from '@ngrx/store';
2+
import {CurrentSearch} from "./current-search.model";
3+
import {ProximitySelector} from "../location/proximity-selector.component";
4+
5+
export const locationReducer: ActionReducer<CurrentSearch> = (state: CurrentSearch, action: Action) => {
6+
console.log(`reduce 2 -> ${action.type}`);
7+
switch (action.type) {
8+
case ProximitySelector.StoreEvents.position:
9+
const update = {
10+
position: {
11+
latitude: action.payload.position.latitude,
12+
longitude: action.payload.position.longitude
13+
}
14+
};
15+
return Object.assign({}, state, update);
16+
case ProximitySelector.StoreEvents.off:
17+
const update = {
18+
position: null,
19+
radius: null
20+
};
21+
return Object.assign({}, state, update);
22+
case ProximitySelector.StoreEvents.radius:
23+
const update = { radius: action.payload.radius };
24+
return Object.assign({}, state, update);
25+
default:
26+
return state;
27+
}
28+
};

app/components/youtube-search/search.reducer.ts renamed to app/components/reducers/search.reducer.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { ActionReducer, Action } from '@ngrx/store';
2+
import {SearchBox} from "../search-box/search-box.component";
3+
import {CurrentSearch} from "./current-search.model";
24

3-
export interface CurrentSearch {
4-
text: string
5-
}
65

76
export const searchReducer: ActionReducer<CurrentSearch> = (state: CurrentSearch, action: Action) => {
7+
console.log(`reduce 1 -> ${action.type}`);
88
switch (action.type) {
9-
case 'TEXT':
9+
case SearchBox.StoreEvents.text:
1010
const update = { text: action.payload.text };
1111
return Object.assign({}, state, update);
1212
default:

app/components/search-box/search-box.component.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {Observable} from "rxjs/Rx";
22
import {ElementRef, OnInit, Component, Input} from "@angular/core";
3-
import {CurrentSearch} from "../youtube-search/search.reducer";
3+
import {CurrentSearch} from "../reducers/search.reducer";
44
import {Store} from "@ngrx/store";
55

66
@Component({
@@ -12,6 +12,10 @@ import {Store} from "@ngrx/store";
1212
})
1313

1414
export class SearchBox implements OnInit {
15+
16+
static StoreEvents = {
17+
text: 'SearchBox:TEXT_CHANGED'
18+
};
1519

1620
@Input()
1721
store: Store<any>;
@@ -25,7 +29,7 @@ export class SearchBox implements OnInit {
2529
.debounceTime(250)
2630
.subscribe((text: string) =>
2731
this.store.dispatch({
28-
type: 'TEXT',
32+
type: SearchBox.StoreEvents.text,
2933
payload: {
3034
text: text
3135
}

0 commit comments

Comments
 (0)