【问题标题】:Saving data within a service in Angular 2在 Angular 2 的服务中保存数据
【发布时间】:2017-05-14 08:24:36
【问题描述】:

我正在使用一项服务,以便在用户输入文本框时从 api 中提取数据。在用户单击项目的详细信息页面之前,一切都很好。应用程序路由到项目,然后在应用程序内按下后退按钮时,用户的输入不会保存,输入和电影列表组件为空。

问题:我正在寻找保存此输入的 Angular 2 方式,以便当用户返回电影列表时,他们之前的搜索查询的数据就在那里

用户在这里输入他们的电影标题,在用户停止输入后,电影服务会返回一个 observable。

search-textbox.component.ts

import { Component, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { MovieService } from '../movie.service';
import { Observable } from 'rxjs/Rx';

@Component({
  selector: 'app-search-textbox',
  templateUrl: './search-textbox.component.html',
  styleUrls: ['./search-textbox.component.scss'],
  providers: [MovieService]
})
export class SearchTextboxComponent implements OnInit {

  private movies;
  private title = new FormControl();

  constructor(private movieService: MovieService) {
    this.title.valueChanges
             .debounceTime(400)
             .distinctUntilChanged()
             .flatMap(title => this.movieService.getMovies(title))
             .subscribe(movies => this.movies = movies);
  }

  ngOnInit() {}

}

search-textbox.component.html

<div class="row searchbox">
  <div class="col-md-12">
    <input type="text" [formControl]="title" placeholder="Enter Title" autofocus/>
  </div>
</div>
<div class="row" [class.loading]="!movies && title.value ">
  <app-movie-list [movies]="movies"></app-movie-list>
</div>

电影列表组件可以通过输入装饰器访问从 api 调用返回的电影。

movie-list.component.ts

import { Component, OnInit, Input } from '@angular/core';
import { Router } from '@angular/router';

import { MovieService } from '../movie.service';

@Component({
  selector: 'app-movie-list',
  templateUrl: './movie-list.component.html',
  styleUrls: ['./movie-list.component.scss'],
  providers: [MovieService]
})
export class MovieListComponent implements OnInit {
  @Input() movies: Object[];

  constructor(
    private router: Router,
    private movieService: MovieService
  ) {}

  ngOnInit() {}

  gotoDetail(selectedMovieID): void {
    this.router.navigate(['./detail', selectedMovieID])
  }
}

movie-list.component.html

<div *ngFor="let movie of movies">
  <div *ngIf="movie.Poster != 'N/A'"
       class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
     <div class="card">
       <img class="card-img-top" [src]="movie.Poster" alt="Card image cap">
       <div class="card-block">
         <h4 class="card-title">{{movie.Title}}</h4>
         <p class="card-text">{{movie.Year}}</p>
         <button (click)="gotoDetail(movie.imdbID)" class="btn btn-success">Details</button>
       </div>
     </div>
  </div>
</div>

当用户通过 this.location.back() 重新路由返回时,搜索输入为空

movie-detail.component.ts

import { Component, OnInit } from '@angular/core';
import { MovieService } from '../movie.service';
import { ActivatedRoute, Params } from '@angular/router';
import { Location } from '@angular/common';

@Component({
  selector: 'app-movie-detail',
  templateUrl: './movie-detail.component.html',
  styleUrls: ['./movie-detail.component.scss'],
  providers: [MovieService]
})

export class MovieDetailComponent implements OnInit {
  private movie: Object;

  constructor(
    private movieService: MovieService,
    private route: ActivatedRoute,
    private location: Location
  ) {}

  ngOnInit() {
    this.route.params
        .switchMap((params: Params) => this.movieService.getMovieDetails(params['id']))
        .subscribe((movie: Object) => this.movie = movie)
  }

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

}

movie-detail.component.html

<div *ngIf="movie">
  <div class="row">
    <div class="col-md-6">
      <img [src]="movie.Poster" />
    </div>
    <div class="col-md-6 movie-details">
      <h1>{{movie.Title}}: {{movie.Year}}</h1>
      <div *ngIf="movie.tomatoMeter != 'N/A'">
        <progress class="progress progress-striped progress-success" [class.progress-danger]="movie.tomatoMeter < 50" value="{{movie.tomatoMeter}}" max="100"></progress>
        <h1>{{movie.tomatoMeter}}%</h1>
        <div class="consensus">
          <p>{{movie.tomatoConsensus}}</p>
        </div>
      </div>
    </div>
  </div>
  <button (click)="goBack()" class="btn btn-info">Go Back</button>
</div>

movie.service.ts

import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import {Observable} from 'rxjs/Rx';

@Injectable()
export class MovieService {

  constructor (private http: Http) {}

  private moviesUrl = 'http://omdbapi.com?s=';
  private movieDetailsUrl = 'http://omdbapi.com?i=';

  getMovies(searchInput: string) : Observable<Object[]>{
    return this.http.get(this.moviesUrl + searchInput)
                    .map((res:Response) => res.json().Search)
                    .catch((error:any) => Observable.throw(error.json().error || 'error'));
  }

  getMovieDetails(movieID: string) : Observable<Object> {
    return this.http.get(this.movieDetailsUrl + movieID + '&tomatoes=true') // add rotten tomatoes param
                    .map((r: Response) => r.json())
                    .catch((error:any) => Observable.throw(error.json().error || 'error'));
  }

}

【问题讨论】:

    标签: javascript angularjs frontend


    【解决方案1】:

    在路由加载时不保留参数。

    您需要将它们临时存储在会话存储/位置存储中。

    1. 在 List Page 路由的 CanDeActivate() 上,将它们存储在 Location/Session Storage 中
    2. 在 SearchTextboxComponent 中的 ngOnInit() 方法中,从存储中读取并将其绑定到模板中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-29
      • 2017-03-16
      • 1970-01-01
      • 1970-01-01
      • 2017-11-15
      • 2014-01-23
      相关资源
      最近更新 更多