ANGULAR 2 和 EXPRESS
The last part is to connect the Angular app to the express server. To do this, we'll need to make some modifications to our angular 2 app to consume the express api.
mean-docker/angular-client/src/app/app.component.ts
import { Component, OnInit } from '@angular/core';
import { Http } from '@angular/http';
// Import rxjs map operator
import 'rxjs/add/operator/map';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'app works!';
// Link to our api, pointing to localhost
API = 'http://localhost:3000';
// Declare empty list of people
people: any[] = [];
constructor(private http: Http) {}
// Angular 2 Life Cycle event when component has been initialized
ngOnInit() {
this.getAllPeople();
}
// Add one person to the API
addPerson(name, age) {
this.http.post(`${this.API}/users`, {name, age})
.map(res => res.json())
.subscribe(() => {
this.getAllPeople();
})
}
// Get all users from the API
getAllPeople() {
this.http.get(`${this.API}/users`)
.map(res => res.json())
.subscribe(people => {
console.log(people)
this.people = people
})
}
}
Angular 2 style guides usually recommends separating most logic into a service/provider. We've placed all the code in the component here for brevity.
We've imported theOnInitinterface, to call events when the component is initialized, then added a two methodsAddPersonandgetAllPeople, that call the API.
Notice that this time round, ourAPIis pointing tolocalhost. This is because while the angular 2 app will be running inside the container, it's served to the browser. And the browser is the one that makes request. It will thus make a request to the exposed express API. As a result, we don't need to link Angular and Express in thedocker-compose.ymlfile.
Next, we need to make some changes to the template. I first added bootstrap via cdn to theindex.html
mean-docker/angular-client/src/app/index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Angular Client</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CDN -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root>Loading...</app-root>
</body>
</html>
Then update the app.component.html template
mean-docker/angular-client/src/app/app.component.html
<!-- Bootstrap Navbar -->
<nav class="navbar navbar-light bg-faded">
<div class="container">
<a class="navbar-brand" href="#">Mean Docker</a>
</div>
</nav>
<div class="container">
<div [style.margin-top.px]="10" class="row">
<h3>Add new person</h3>
<form class="form-inline">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" #name>
</div>
<div class="form-group">
<label for="age">Age</label>
<input type="number" class="form-control" id="age" #age>
</div>
<button type="button" (click)="addPerson(name.value, age.value)" class="btn btn-primary">Add person</button>
</form>
</div>
<div [style.margin-top.px]="10" class="row">
<h3>People</h3>
<!-- Bootstrap Card -->
<div [style.margin-right.px]="10" class="card card-block col-md-3" *ngFor="let person of people">
<h4 class="card-title">{{person.name}} {{person.age}}</h4>
</div>
</div>
</div>
The above template shows the components properties and bindings. We are almost done.
Since we've made changes to our code, we need to do a build for our Docker Compose
$ docker-compose up --build
The--buildflag tells docker compose that we've made changes and it needs to do a clean build of our images.
Once this is done, go tolocalhost:4200in your browser,
We are getting aNo 'Access-Control-Allow-Origin'error. To quickly fix this, we need to enable Cross-Origin in our express app. We'll do this with a simple middleware.
mean-docker/express-server/server.js
// Code commented out for brevity
// Parsers for POST data
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// Cross Origin middleware
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*")
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
next()
})
// Set our api routes
app.use('/', api);
// Code commented out for brevity
We can now run docker-compose again with the build flag. You should be in themean-docker directory
$ docker-compose up --build
Going tolocalhost:4200on the browser.