Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
},
"private": true,
"dependencies": {
"@angular-redux/form": "^5.1.0-beta.0",
"@angular-redux/router": "2.0.0-alpha.3",
"@angular-redux/store": "^5.1.0",
"@angular/common": "^2.3.1",
"@angular/compiler": "^2.3.1",
"@angular/core": "^2.3.1",
Expand All @@ -21,8 +24,6 @@
"@angular/platform-browser": "^2.3.1",
"@angular/platform-browser-dynamic": "^2.3.1",
"@angular/router": "^3.3.1",
"@angular-redux/store": "^5.1.0",
"@angular-redux/router": "2.0.0-alpha.3",
"core-js": "^2.4.1",
"redux": "^3.6.0",
"redux-observable": "^0.12.2",
Expand Down
8 changes: 8 additions & 0 deletions src/app/app.component.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,11 @@
border-radius: 3px;
padding: 5px;
}

content {
display: block;
padding: 10px;
border: solid gray 1px;
border-radius: 5px;
margin-top: 1rem;
}
6 changes: 5 additions & 1 deletion src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@ <h1>
<nav>
<a routerLink="/elephants" routerLinkActive="active">Elephants</a>
<a routerLink="/lions" routerLinkActive="active">Lions</a>
<a routerLink="/feedback" routerLinkActive="active">Feedback</a>
</nav>
<router-outlet></router-outlet>

<content>
<router-outlet></router-outlet>
</content>
16 changes: 10 additions & 6 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Component } from '@angular/core';
import { NgRedux, DevToolsExtension } from '@angular-redux/store';
import { NgReduxRouter, routerReducer } from '@angular-redux/router';
import { provideReduxForms, composeReducers, defaultFormReducer } from '@angular-redux/form';
import { Action, combineReducers } from 'redux';
import { createEpicMiddleware, combineEpics } from 'redux-observable';

Expand All @@ -27,11 +28,13 @@ export class AppComponent {
elephantsEpics: ElephantsEpics,
lionsEpics: LionsEpics
) {
const rootReducer = combineReducers({
elephants: elephantsReducer,
lions: lionsReducer,
router: routerReducer,
});
const rootReducer = composeReducers(
defaultFormReducer(),
combineReducers({
elephants: elephantsReducer,
lions: lionsReducer,
router: routerReducer,
}));

ngRedux.configureStore(
rootReducer,
Expand All @@ -41,7 +44,8 @@ export class AppComponent {
createEpicMiddleware(combineEpics(...lionsEpics.epics)),
],
devTools.isEnabled() ? [ devTools.enhancer() ] : null);
ngReduxRouter.initialize(/* args */);
ngReduxRouter.initialize();
provideReduxForms(ngRedux);
}

ngOnInit() {
Expand Down
2 changes: 2 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { AppActions } from './app.actions';

import { ElephantsModule } from './elephants/elephants.module';
import { LionsModule } from './lions/lions.module';
import { FeedbackModule } from './feedback/feedback.module';

@NgModule({
declarations: [ AppComponent ],
Expand All @@ -24,6 +25,7 @@ import { LionsModule } from './lions/lions.module';
NgReduxRouterModule,
ElephantsModule,
LionsModule,
FeedbackModule,
],
providers: [ AppActions ],
bootstrap: [ AppComponent ]
Expand Down
5 changes: 4 additions & 1 deletion src/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { ElephantListComponent } from './elephants/elephant-list/elephant-list.component';
import { LionListComponent } from './lions/lion-list/lion-list.component';
import { FeedbackFormComponent } from './feedback/feedback-form/feedback-form.component';

export const appRoutes = [
{ path: '', redirectTo: '/elephants', pathMatch: 'full' },
{ path: 'elephants', component: ElephantListComponent },
{ path: 'lions', component: LionListComponent }
{ path: 'lions', component: LionListComponent },
{ path: 'feedback', component: FeedbackFormComponent },
];
2 changes: 1 addition & 1 deletion src/app/elephants/elephant-list/elephant-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { select } from '@angular-redux/store';
export class ElephantListComponent {
// Shorthand for
// constructor(ngRedux: NgRedux { this.elephants$ = ngRedux.select('elephants'); })
@select() elephants$
@select() readonly elephants$

// Since we're observing an array of items, we need to set up a 'trackBy'
// parameter so Angular doesn't tear down and rebuild the list's DOM every
Expand Down
4 changes: 2 additions & 2 deletions src/app/elephants/elephants.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { Action } from 'redux';

@Injectable()
export class ElephantsActions {
static LOAD_SUCCEEDED = 'LOAD_SUCCEEDED(ELEPHANTS)';
static LOAD_FAILED = 'LOAD_SUCCEEDED(ELEPHANTS)';
static readonly LOAD_SUCCEEDED = 'LOAD_SUCCEEDED(ELEPHANTS)';
static readonly LOAD_FAILED = 'LOAD_FAILED(ELEPHANTS)';

loadSucceeded(payload) {
return {
Expand Down
8 changes: 4 additions & 4 deletions src/app/elephants/elephants.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ import { Http } from '@angular/http';
import 'rxjs/add/operator/map';

// A fake API on the internets.
const BASE_URL = 'http://jsonplaceholder.typicode.com';
const ELEPHANTS_URL = 'http://www.mocky.io/v2/588d70ad100000e50f2d2983';

@Injectable()
export class ElephantsService {
constructor(private http: Http) {}

getAll() {
return this.http.get(BASE_URL + '/users')
return this.http.get(ELEPHANTS_URL)
.map(resp => resp.json())
.map(records => records.map(
record => ({
animalType: 'Elephant',
name: record.name.split(' ')[0],
animalType: record.type,
name: record.name,
})));
}
}
21 changes: 21 additions & 0 deletions src/app/feedback/feedback-form/feedback-form.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
label {
display: block;
width: 100%;
margin-bottom: 1rem;
}

input, textarea {
display: block;
width: 95%;
padding: 5px;
border: solid gray 1px;
border-radius: 5px;
}

textarea {
height: 250px;
}

.footnote {
font-style: italic;
}
42 changes: 42 additions & 0 deletions src/app/feedback/feedback-form/feedback-form.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<form connect="feedback">
<h2>Feedback Form</h2>

<p>
Did you enjoy your time at the zoo? Let us know using
the form below.
<p>

<label for="firstName">
First Name:
<input
name="firstName"
type="text"
maxLength="25"
ngControl
ngModel />
</label>

<label for="lastName">Last Name:
<input
name="lastName"
type="text"
maxLength="25"
ngControl
ngModel />
</label>

<label for="comments">Comments:
<textarea
name="comments"
[maxLength]="MAX_COMMENT_CHARS"
ngControl
ngModel></textarea>
<p>{{ charsLeft$ | async }} characters remaining.
</label>

<button>Send!</button>

<p class="footnote">
(<sup>*</sup>doesn't really send anything - this is just a demo after all.)
</p>
</form>
21 changes: 21 additions & 0 deletions src/app/feedback/feedback-form/feedback-form.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Component } from '@angular/core';
import { Connect, FormStore } from '@angular-redux/form';
import { NgRedux } from '@angular-redux/store';
import { Observable } from 'rxjs';
import { of } from 'rxjs/observable/of';

@Component({
selector: 'feedback-form',
templateUrl: './feedback-form.component.html',
styleUrls: [ './feedback-form.component.css' ],
})
export class FeedbackFormComponent {
readonly MAX_COMMENT_CHARS = 300;
readonly charsLeft$: Observable<number>;

constructor(store: NgRedux<any>) {
this.charsLeft$ = store.select<string>(['feedback', 'comments'])
.map(comments => comments || '')
.map(comments => this.MAX_COMMENT_CHARS - comments.length);
}
}
18 changes: 18 additions & 0 deletions src/app/feedback/feedback.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { NgModule } from '@angular/core'
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { NgReduxForms } from '@angular-redux/form';
import { FeedbackFormComponent } from './feedback-form/feedback-form.component';

@NgModule({
declarations: [ FeedbackFormComponent ],
providers: [ ],
imports: [
CommonModule,
NgReduxForms,
FormsModule,
ReactiveFormsModule
],
exports: [ FeedbackFormComponent ],
})
export class FeedbackModule {}
2 changes: 1 addition & 1 deletion src/app/lions/lion-list/lion-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { select } from '@angular-redux/store';
export class LionListComponent {
// Shorthand for
// constructor(ngRedux: NgRedux { this.lions$ = ngRedux.select('lions'); })
@select() lions$
@select() readonly lions$

// Since we're observing an array of items, we need to set up a 'trackBy'
// parameter so Angular doesn't tear down and rebuild the list's DOM every
Expand Down
4 changes: 2 additions & 2 deletions src/app/lions/lions.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { Action } from 'redux';

@Injectable()
export class LionsActions {
static LOAD_SUCCEEDED = 'LOAD_SUCCEEDED(LIONS)';
static LOAD_FAILED = 'LOAD_SUCCEEDED(LIONS)';
static readonly LOAD_SUCCEEDED = 'LOAD_SUCCEEDED(LIONS)';
static readonly LOAD_FAILED = 'LOAD_FAILED(LIONS)';

loadSucceeded(payload) {
return {
Expand Down
8 changes: 4 additions & 4 deletions src/app/lions/lions.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ import { Http } from '@angular/http';
import 'rxjs/add/operator/map';

// A fake API on the internets.
const BASE_URL = 'http://jsonplaceholder.typicode.com';
const LIONS_URL = 'http://www.mocky.io/v2/588d702d100000d50f2d2980';

@Injectable()
export class LionsService {
constructor(private http: Http) {}

getAll() {
return this.http.get(BASE_URL + '/users')
return this.http.get(LIONS_URL)
.map(resp => resp.json())
.map(records => records.map(
record => ({
animalType: 'Lion',
name: record.name.split(' ')[0],
animalType: record.type,
name: record.name,
})));
}
}
Loading