subscribe メソッドから受け取った値をテンプレート変数に格納することはできません。
写真詳細コンポーネント
import { Component, OnInit, Input } from "@angular/core";
import { PhotoSevice } from "../photo.service";
import { Photo } from "src/app/model/photo.model";
@Component({
selector: "app-photo-detail",
templateUrl: "./photo-detail.component.html",
styleUrls: ["./photo-detail.component.css"]
})
export class PhotoDetailComponent implements OnInit {
url: string;
constructor(private photoService: PhotoSevice) {
this.photoService.photoSelected.subscribe(data => {
this.url = data;
console.log(this.url);
});
console.log(this.url);
}
ngOnInit() {
}
}
外部のconsole.logはundefinedになり、ビューには何もレンダリングされませんが、subscibeメソッドの内部では値を見ることができます。どうすればビューに表示できますか?
写真コンポーネント
import { Component, OnInit } from "@angular/core";
import { ActivatedRoute, Params, Router } from "@angular/router";
import { FnParam } from "@angular/compiler/src/output/output_ast";
import { AlbumService } from "../service/album.service";
import { Photo } from "../model/photo.model";
import { PhotoSevice } from "./photo.service";
@Component({
selector: "app-photos",
templateUrl: "./photos.component.html",
styleUrls: ["./photos.component.css"]
})
export class PhotosComponent implements OnInit {
selectedAlbumId: string;
photoList: Photo[] = [];
photoSelected: Photo;
isLoading: Boolean;
constructor(
private rout: ActivatedRoute,
private albumService: AlbumService,
private router: Router,
private photoService: PhotoSevice
) { }
ngOnInit() {
this.isLoading = true;
this.rout.params.subscribe((params: Params) => {
this.selectedAlbumId = params["id"];
this.getPhotos(this.selectedAlbumId);
});
}
getPhotos(id: string) {
this.albumService.fetchPhotos(this.selectedAlbumId).subscribe(photo => {
this.photoList = photo;
this.isLoading = false;
});
}
displayPhoto(url: string, title: string) {
console.log(url);
this.photoService.photoSelected.emit(url);
this.router.navigate(["/photo-detail"]);
}
}
テンプレート ビューでのサブスクライブと非同期呼び出しから受け取った値を保存して表示できるように、これがどのように機能し、どのように回避するかを説明してください。
これが 2 つのコンポーネントのビューです---
photo.component.html
<div *ngIf="isLoading">
<h3>Loading...</h3>
</div>
<div class="container" *ngIf="!isLoading">
<div class="card-columns">
<div *ngFor="let photo of photoList" class="card">
<img
class="card-img-top"
src="{{ photo.thumbnailUrl }}"
alt="https://source.unsplash.com/random/300x200"
/>
<div class="card-body">
<a
class="btn btn-primary btn-block"
(click)="displayPhoto(photo.url, photo.title)"
>Enlarge Image</a
>
</div>
</div>
</div>
</div>
写真詳細.component.ts
<div class="container">
<div class="card-columns">
<div class="card">
<img class="card-img-top" src="{{ url }}" />
</div>
</div>
</div>
photo.service.ts
import { Injectable } from "@angular/core";
import { EventEmitter } from "@angular/core";
@Injectable({ providedIn: "root" })
export class PhotoSevice {
photoSelected = new EventEmitter();
// urlService: string;
}
これは私のgithubリポジトリへのリンクです。コードをコメントに残し、そこで別のアプローチを使用しました。そこのアルバムコンポーネントを確認すると、httpリクエストにサブスクライブし、アルバムコンポーネントのテンプレート変数に値を割り当てました。また、値は subscibe メソッドの外側で未定義として表示されますが、テンプレートでアクセスできます。
https://github.com/Arpan619Banerjee/angular-accelerate
アルバム コンポーネントとサービスの詳細は次のとおりです。 これをイベント エミッタのケースと比較して、違いを説明してください -- albums.component.ts
import { Component, OnInit } from "@angular/core";
import { AlbumService } from "../service/album.service";
import { Album } from "../model/album.model";
@Component({
selector: "app-albums",
templateUrl: "./albums.component.html",
styleUrls: ["./albums.component.css"]
})
export class AlbumsComponent implements OnInit {
constructor(private albumService: AlbumService) {}
listAlbums: Album[] = [];
isLoading: Boolean;
ngOnInit() {
this.isLoading = true;
this.getAlbums();
}
getAlbums() {
this.albumService.fetchAlbums().subscribe(data => {
this.listAlbums = data;
console.log("inside subscibe method-->" + this.listAlbums); // we have data here
this.isLoading = false;
});
console.log("outside subscribe method----->" + this.listAlbums); //empty list==== but somehow we have the value in the view , this doesn t work
//for my photo and photo-detail component.
}
}
アルバム.コンポーネント.html
<div *ngIf="isLoading">
<h3>Loading...</h3>
</div>
<div class="container" *ngIf="!isLoading">
<h3>Albums</h3>
<app-album-details
[albumDetail]="album"
*ngFor="let album of listAlbums"
></app-album-details>
</div>
アルバム.サービス.ts
import { Injectable } from "@angular/core";
import { HttpClient, HttpParams } from "@angular/common/http";
import { map, tap } from "rxjs/operators";
import { Album } from "../model/album.model";
import { Observable } from "rxjs";
import { UserName } from "../model/user.model";
@Injectable({ providedIn: "root" })
export class AlbumService {
constructor(private http: HttpClient) {}
albumUrl = "http://jsonplaceholder.typicode.com/albums";
userUrl = "http://jsonplaceholder.typicode.com/users?id=";
photoUrl = "http://jsonplaceholder.typicode.com/photos";
//get the album title along with the user name
fetchAlbums(): Observable<any> {
return this.http.get<Album[]>(this.albumUrl).pipe(
tap(albums => {
albums.map((album: { userId: String; userName: String }) => {
this.fetchUsers(album.userId).subscribe((user: any) => {
album.userName = user[0].username;
});
});
// console.log(albums);
})
);
}
//get the user name of the particular album with the help of userId property in albums
fetchUsers(id: String): Observable<any> {
//let userId = new HttpParams().set("userId", id);
return this.http.get(this.userUrl + id);
}
//get the photos of a particular album using the albumId
fetchPhotos(id: string): Observable<any> {
let selectedId = new HttpParams().set("albumId", id);
return this.http.get(this.photoUrl, {
params: selectedId
});
}
}
コメントで説明されているように、偶数エミッターにコンソール ログを追加しましたが、これは予想される動作です。