Step 1: Use the Angular CLI to bootstrap a new Angular app
npm install -g @angular/cli
Step 2: Create a new Angular app
Use the Angular CLI to create a new app
ng new angular-tour-of-heroes
This creates the following directory
~/environment/angular-tour-of-heroes
├── e2e/ ## IGNORE FOR NOW
├── node_modules/
├── src/
│ ├── app/
| │ ├── app.component.css ## WE WILL MODIFY THIS
| │ ├── app.component.html ## WE WILL MODIFY THIS
| │ ├── app.component.spec.ts ## IGNORE FOR NOW
| │ └── app.module.ts ## WE WILL MODIFY THIS
│ ├── assets/
| │ └── .gitkeep
│ ├── environments/
| │ ├── environment.prod.ts
| │ └── environments.ts
│ ├── favicon.ico
│ ├── main.ts
│ ├── polyfills.ts
│ ├── styles.css
│ └── tests.ts
├── .browserslistrc ## IGNORE FOR NOW
├── .gitignore
├── angular.json
├── karma.conf.js ## IGNORE FOR NOW
├── package-lock.json
├── package.json
├── README.md
├── tsconfig.app.json ## IGNORE FOR NOW
├── tsconfig.json ## IGNORE FOR NOW
├── tsconfig.spec.json ## IGNORE FOR NOW
└── tslint.json ## IGNORE FOR NOW
Modify /src/polyfills.ts for Angular 6+ Support
(window as any).global = window;
(window as any).process = {
env: { DEBUG: undefined },
};
Step 3: Run Unit & E2E Tests
Execute the unit tests via Karma .
Step 4: Build & Serve the application
cd angular-tour-of-heroes
ng build OR npm run-script build
ng serve --open OR nom start
Step 5: Manually Add Amplify Backend
Create file /src/aws-exports.ts
"aws_project_region": "ap-southeast-1",
"aws_cognito_identity_pool_id": "ap-southeast-1:f71d7e8f-8235-41e4-9bca-8fe6c00eb5e4",
"aws_cognito_region": "ap-southeast-1",
"aws_user_pools_id": "ap-southeast-1_pfV9SAIvf",
"aws_user_pools_web_client_id": "23t9cniohmsk313lpogmv6v33b",
"oauth": {
"domain": "materialpwa-dev.auth.ap-southeast-1.amazoncognito.com",
"scope": [
"phone",
"email",
"openid",
"profile",
"aws.cognito.signin.user.admin"
],
"redirectSignIn": "http://localhost:4200/auth/",
"redirectSignOut": "http://localhost:4200/auth/signin/",
"responseType": "code"
},
"federationTarget": "COGNITO_USER_POOLS",
"aws_user_files_s3_bucket": "angularpwapostone283fb76bded24ac2b6110d4234facb214913-dev",
"aws_user_files_s3_bucket_region": "ap-southeast-1"
Add the following to .gitignore
#amplify
amplify/\#current-cloud-backend
amplify/.config/local-*
amplify/logs
amplify/mock-data
amplify/backend/amplify-meta.json
amplify/backend/awscloudformation
amplify/backend/.temp
build/
dist/
node_modules/
aws-exports.js
awsconfiguration.json
amplifyconfiguration.json
amplify-build-config.json
amplify-gradle-config.json
amplifytools.xcconfig
.secret-*
Install Amplify Libraries
npm install --save aws-amplify @aws-amplify/ui-angular
npm start
Importing the Amplify Angular UI Module. Add Amplify Angular UI Module to /src/app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
/* import AmplifyUIAngularModule */
import { AmplifyUIAngularModule } from '@aws-amplify/ui-angular';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
/* configure app with AmplifyUIAngularModule */
AmplifyUIAngularModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Step 6: Connect API and database to the app
Connect frontend to API Modify. Add the following to /src/main.ts
import Amplify from 'aws-amplify';
import aws_exports from './aws-exports';
Amplify.configure(aws_exports);
Update tsconfig.app.json to include the “node” compiler option in types:
"compilerOptions": {
"types" : ["node"]
}
Step 7: Add Angular Material Components // TODO
import {Component} from '@angular/core';
/**
* @title Toolbar overview
*/
@Component({
selector: 'toolbar-overview-example',
templateUrl: 'toolbar-overview-example.html',
styleUrls: ['toolbar-overview-example.css'],
})
export class ToolbarOverviewExample {}
.example-spacer {
flex: 1 1 auto;
}
Add the tag to the app.component.html like so:
<p>
<mat-toolbar color="primary">
<button mat-icon-button class="example-icon" aria-label="Example icon-button with menu icon">
<mat-icon>menu</mat-icon>
</button>
<span>My App</span>
<span class="example-spacer"></span>
<button mat-icon-button class="example-icon favorite-icon" aria-label="Example icon-button with heart icon">
<mat-icon>favorite</mat-icon>
</button>
<button mat-icon-button class="example-icon" aria-label="Example icon-button with share icon">
<mat-icon>share</mat-icon>
</button>
</mat-toolbar>
</p>
Step 8: Add Navigation & Routing //TODO
Landing Page
Sign Up
Sign In
Dashboard
Hero Create
Hero Read
Hero Update
Hero Delete
Hero Index
Step 9: Add Hero Components
Create the heroes component
ng generate component heroes
CREATE src/app/heroes/heroes.component.css (0 bytes)
CREATE src/app/heroes/heroes.component.html (21 bytes)
CREATE src/app/heroes/heroes.component.spec.ts (626 bytes)
CREATE src/app/heroes/heroes.component.ts (275 bytes)
UPDATE src/app/app.module.ts (755 bytes)
Create HeroDetailComponent
ng generate component hero-detail
CREATE src/app/hero-detail/hero-detail.component.css (0 bytes)
CREATE src/app/hero-detail/hero-detail.component.html (26 bytes)
CREATE src/app/hero-detail/hero-detail.component.spec.ts (655 bytes)
CREATE src/app/hero-detail/hero-detail.component.ts (294 bytes)
UPDATE src/app/app.module.ts (922 bytes)
export type Hero = {
id : string,
name : string
};
Add data to your database by modifying /src/app/app.component.ts
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { APIService } from './API.service';
import { Hero } from '../types/hero';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'amplify-angular-app';
public createForm: FormGroup;
constructor(private api: APIService, private fb: FormBuilder) { }
async ngOnInit() {
this.createForm = this.fb.group({
'name': ['', Validators.required]
});
}
public onCreate(hero: Hero) {
this.api.CreateHero(hero).then(event => {
console.log('item created!');
this.createForm.reset();
})
.catch(e => {
console.log('error creating hero...', e);
});
}
}
Enable Angular Forms modules in /src/app/app.module.ts:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AmplifyUIAngularModule } from '@aws-amplify/ui-angular';
/* new form imports */
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
AmplifyUIAngularModule,
/* configuring form modules */
FormsModule,
ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Add form that will be used for creating heroes. Add the following to /src/app/app.component.html
<div class="form-body">
<form autocomplete="off" [formGroup]="createForm" (ngSubmit)="onCreate(createForm.value)">
<div>
<label>Name: </label>
<input type="text" formControlName="name" autocomplete="off">
</div>
<button type="submit">Submit</button>
</form>
</div>
Next, update your AppComponent class so that it will list all heroes in the database when the app starts. To do so, implement OnInit add a ListHeroes query in src/app/app.component.ts. Store the query results in an array.
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { APIService } from './API.service';
import { Hero } from '../types/hero';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'amplify-angular-app';
public createForm: FormGroup;
/* declare heroes variable */
heroes: Array<Hero>;
constructor(private api: APIService, private fb: FormBuilder) { }
async ngOnInit() {
this.createForm = this.fb.group({
'name': ['', Validators.required]
});
/* fetch heroes when app loads */
this.api.ListHeroes().then(event => {
this.heroes = event.items;
});
}
public onCreate(hero: Hero) {
this.api.CreateHero(hero).then(event => {
console.log('item created!');
this.createForm.reset();
})
.catch(e => {
console.log('error creating hero...', e);
});
}
}
Add the following to your /src/app/app.component.html to display any of the heroes you have added:
<div *ngFor="let hero of heroes">
<div>{{ hero.name }}</div>
</div>
Finally, to subscribe to realtime data, update ngOnInit in /src/app/app.component.ts. When the app starts, this code will set up a subscription. The subscription will update the heroes array when new events are received (when a new hero is created):
async ngOnInit() {
this.createForm = this.fb.group({
'name': ['', Validators.required]
});
this.api.ListHeroes().then(event => {
this.heroes = event.items;
});
/* subscribe to new heroes being created */
this.api.OnCreateHeroListener.subscribe( (event: any) => {
const newHero = event.value.data.onCreateHero;
this.heroes = [newHero, ...this.heroes];
});
}
Step 10: Add Hero Service //TODO
Step 11: Add Authentication Components //TODO