Tiven Wang
chevron_rightAngular chevron_rightJavaScript

Training JavaScript - 3. Angular for Frontend Development

Nat Geo Photography‏
Wang Tiven June 19, 2017
425 favorite favorites
bookmark bookmark
share share

是一个大型水鸟科的通称。包括19个品种。在大多数地球上比较温暖的地带都可以见到它们的踪迹。鹳是候鸟,善于飞行。鹳有很长的腿和细长的带蹼的爪子。它们有又长又结实的尖喙。羽毛通常是白色和黑色的。但有些品种鹳的头上或头上和脖子上几乎没有羽毛。

JavaScript Series:

  1. JavaScript Foundation and Node.js
  2. Create a backend server by Node.js (JavaScript version) or Create Server by Node.js (TypeScript version)
  3. Angular for frontend development

Angular is the frontend part of the MEAN stack, consisting of MongoDB database, Express.js web application server framework, Angular itself, and Node.js runtime environment.

We follow the quickstart tutorial of angular to create a application in our JavaScript blog series.

Angular Version 4.2.3

Quickstart

npm install -g @angular/cli

ng new training-javascript-angular

cd training-javascript-angular

ng serve --open

Change the title to ‘Tiven’s App’ in src/app/app.component.ts, then the server will rebuild automatically, and the page in the browser will be refreshed automatically. ng keeps the app transpiling and running.

Try to change styles in the file src/app/app.component.css and view the different on the page.

ng build

Wechat Message App

In the previous article Create a backend server by Node.js (JavaScript version) we have created a server for receiving wechat messages and storing in the database. Next we follow the tutorial Tour of Heroes of angular to create an application wechat message management application for managing the wechat messages.

Component

Show Messages List

Add the message list in the file app.component.html

<ul class="messages">
  <li *ngFor="let message of messages">
    { { message.text } }
  </li>
</ul>

Add the property messages in the AppComponent class.

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Tiven App';
  messages = [{
    text: 'message 1'
  }, {
    text: 'message 2'
  }];
}

Now you can see the message list in the page.

Style the messages

Add css styles in file app.component.css:

.messages li {
  cursor: pointer;
  position: relative;
  left: 0;
  background-color: #EEE;
  margin: .5em;
  padding: .3em 0;
  height: 1.6em;
  border-radius: 4px;
}

Handle click events

export class AppComponent {
  ...

  selectedMessage: any;

  onSelect(message: any): void {
    this.selectedMessage = message;
  }
}
  • onSelect(message: any): void {}
  • selectedMessage: any;
<ul class="messages">
  <li *ngFor="let message of messages" (click)="onSelect(message)">
    
  </li>
</ul>

<div>
  <h2>selected message</h2>
  <div></div>
</div>
  • (click)="onSelect(message)"
  • <div></div>
<div *ngIf="selectedMessage">
</div>

Data Model

Declare the data model type in a independent class:

message.ts:

export class Message {
  id: number;
  type: string;
  text: string;
}

Change the data type declaration in the component class:

selectedMessage: Message;

onSelect(message: Message): void {
  this.selectedMessage = message;
}

Services

Split the service logic into a service class:

message.service.ts:

import { Injectable } from '@angular/core';

import { Message }   from './message';

@Injectable()
export class MessageService {
  getMessages(): Message[] {
    return [
      {
        id: 1,
        type: 'subscribe',
        text: 'message 1'
      }, {
        id: 2,
        type: 'unsubscribe',
        text: 'message 2'
      }
    ];
  }
}
  • @Injectable()

app.component.ts:

...

import { MessageService }   from './message.service';

@Component({
  ...
  providers: [MessageService]
})
export class AppComponent implements OnInit {
  ...
  messages: Message[];

  constructor(
    private messageService: MessageService
  ) {}

  ngOnInit(): void {
    this.messages = this.messageService.getMessages();
  }

  selectedMessage: Message;

  onSelect(message: Message): void {
    this.selectedMessage = message;
  }
}
  • messages: Message[];
  • providers: [MessageService]
  • constructor(private messageService: MessageService) {}
  • ngOnInit(): void {this.messages = this.messageService.getMessages();}

HTTP Service

import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';

import 'rxjs/add/operator/toPromise';

import { Message }   from './message';

@Injectable()
export class MessageService {

  private messagesUrl = 'http://localhost:6001/api/message';

  constructor(private http: Http) { }

  getMessages(): Promise<Message[]> {
    return this.http.get(this.messagesUrl)
               .toPromise()
               .then(response => response.json() as Message[])
               .catch(this.handleError);
  }

  private handleError(error: any): Promise<any> {
    console.error('An error occurred', error); // for demo purposes only
    return Promise.reject(error.message || error);
  }
}
  • import { Headers, Http } from '@angular/http';
  • import 'rxjs/add/operator/toPromise';
  • constructor(private http: Http) { }
  • getMessages(): Promise<Message[]> {
  • this.http.get(this.messagesUrl).toPromise().then()
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { HttpModule }    from '@angular/http';

import { AppComponent } from './app.component';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
  • import { HttpModule } from '@angular/http';
  • imports: [BrowserModule, HttpModule]

app.component.ts:

ngOnInit(): void {
  this.messageService.getMessages().then((messages)=> {
    this.messages = messages;
  });
}

Routing

Split Message Detail View into a Component

Create file message-detail.component.ts:

import 'rxjs/add/operator/switchMap';
import { Component, OnInit }      from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { Location }               from '@angular/common';

import { Message }        from './message';
import { MessageService } from './message.service';

@Component({
  selector: 'message-detail',
  templateUrl: './message-detail.component.html',
  styleUrls: [ './message-detail.component.css' ]
})
export class MessageDetailComponent implements OnInit {
  message: Message;

  constructor(
    private messageService: MessageService,
    private route: ActivatedRoute,
    private location: Location
  ) {}

  ngOnInit(): void {
    this.route.params
      .switchMap((params: Params) => this.messageService.getMessage(+params['id']))
      .subscribe(message => this.message = message);
  }

  goBack(): void {
    this.location.back();
  }
}

Create file message-detail.component.html:

<div *ngIf="message">
  <h2> details!</h2>
  <div>
    <label>type: </label></div>
  <div>
    <label>text: </label>
    <input [(ngModel)]="message.text" placeholder="text" />
   </div>
  <button (click)="goBack()">Back</button>
</div>

Add method getMessage in class file message.service.ts

getMessage(id: number): Promise<Message> {
  const url = `${this.messagesUrl}/${id}`;
  return this.http.get(url)
    .toPromise()
      .then(response => response.json() as Message)
      .catch(this.handleError);;
}

Add routes in Root Module

import { RouterModule, Routes } from '@angular/router';
...
const routes: Routes = [
  { path: 'message/:id',     component: MessageDetailComponent }
];

@NgModule({
  declarations: [
    AppComponent,
    MessageDetailComponent
  ],
  imports: [
    RouterModule.forRoot(routes),
    ...
  ],
  ...
})
export class AppModule { }
  • import { RouterModule, Routes } from '@angular/router';
  • const routes: Routes = [{ path: 'message/:id', component: MessageDetailComponent }];
  • imports: [RouterModule.forRoot(routes)
  • declarations: [MessageDetailComponent

Add the router outlet in

<router-outlet></router-outlet>

Serve in Express

ng build

copy the files in dist into public in node.js server project.

Add UI Library

References

Similar Posts

  • Training JavaScript Training JavaScript
  • TypeScript Language Overview TypeScript is a superset of JavaScript which primarily provides optional static typing, classes and interfaces. One of the big benefits is to enable IDEs to provide a richer environment for spotting common errors as you type the code. For a large JavaScript project, adopting TypeScript might result in more robust software, while still being deployable where a regular JavaScript application would run.
  • ZeroNet Decentralized websites using Bitcoin crypto and the BitTorrent network. No single point of failure: Site remains online so long as at least 1 peer is serving it. No hosting costs: Sites are served by visitors. Impossible to shut down: It's nowhere because it's everywhere. Fast and works offline: You can access the site even if Internet is unavailable.
  • ES6, ES2016, ES2017
  • Async JavaScript and ReactiveX RxJS RxJS is a library for reactive programming using Observables, to make it easier to compose asynchronous or callback-based code.
  • Training JavaScript - 2. Create Server by Node.js (JavaScript version) Node.js is an open-source, cross-platform JavaScript run-time environment for executing JavaScript code server-side. Historically, JavaScript was used primarily for client-side scripting, in which scripts written in JavaScript are embedded in a webpage's HTML, to be run client-side by a JavaScript engine in the user's web browser. Node.js enables JavaScript to be used for server-side scripting, and runs scripts server-side to produce dynamic web page content before the page is sent to the user's web browser.

Comments

comments powered by Disqus
Back to Top