asyncパイプ Observable経由で渡された値を取得する(ローディング画面を表示)

API

backend/app.yaml

application: angular-gae-go-test
version: 1
runtime: go
api_version: go1.8

handlers:
- url: /apis/(.*)
  script: _go_app
- url: /(.*\.(gif|png|jpeg|jpg|css|js|ico))$
  static_files: dist/\1
  upload: dist/(.*)
- url: /(.*)
  static_files: dist/index.html
  upload: dist/index.html

backend/app.go

package main

import (
    "encoding/json"
    "net/http"
    "time"
)

func init() {
    http.HandleFunc("/apis/user", func(w http.ResponseWriter, r *http.Request) {
        u := User{Name: r.FormValue("name")}
        res, err := json.Marshal(u)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        w.Header().Set("Content-Type", "application/json")
        time.Sleep(3 * time.Second) // APIレスポンスまで3秒間待たせる
        w.Write(res)
    })
}

// User ...
type User struct {
    Name string `json:"name"`
}

angular app

angular-app/src/app/app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule }      from '@angular/core';
import { FormsModule }   from '@angular/forms';
import { HttpModule} from '@angular/http';

import { AppComponent } from './app.component';
import { UserService }  from './user.service'; // サービス登録

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpModule,
    FormsModule
  ],
  providers: [ UserService ], // サービス登録
  bootstrap: [AppComponent]
})
export class AppModule { }

angular-app/src/app/app.component.ts

import { Component } from '@angular/core';
import { Http, URLSearchParams, Headers }  from '@angular/http';
import { UserService } from './user.service';
import { Observable } from 'rxjs/Observable'
import { User } from './user';

@Component({
  selector: 'app-root',
  template: `
    <form>
      <label for="name">名前:</label>
      <input id="name" name="name" type="text" [(ngModel)]="name" />
      <input type="button" (click)="onclick()" value="送信" />
    </form>
    <!-- asyncを利用 -->
    <!--<div>{{(result | async)?.name}}</div>-->
    <div *ngIf="result | async as user; else prog">{{user.name}}</div>
    <ng-template #prog>Now Loading</ng-template>
  `,
})
export class AppComponent {
  name = '';
  // result = '';
  result: Observable<User> =  Observable.create(
    observer => {
      const user: User = {
        name: '',
      };
      observer.next(user);
      observer.complete();
    }
  );

  constructor(private userService: UserService) { } // userServiceの注入

  onclick() {
    this.result = this.userService.getUser(this.name) // subscribeは使わず、Observableオブジェクトをそのまま渡す
  }
}

angular-app/src/app/user.service.ts

import { Injectable } from '@angular/core';
import { User } from './user';
import { Observable } from 'rxjs/Observable'
import { Http, URLSearchParams, Headers }  from '@angular/http';
import 'rxjs/add/operator/map'

@Injectable() // Ingectableデコレーターを付与するとコンポーネントに対してサービスを引き渡せる
export class UserService {
  constructor(private http: Http) { }

  getUser(name: string): Observable<User>{
    let ps = new URLSearchParams();
    ps.set('name', name);
    return this.http.get('apis/user', {
      params: ps
    }).map(res=>res.json() as User);
  }
}

angular-app/src/app/user.ts

export class User {
  name: string;
}