首页 > 解决方案 > Angular: API request based on Input changes

问题描述

I am doing some tests using the SWAPI api (Star Wars); my goal is to call the api as the user clicks on a character list, so a film list where this character has participated can be displayed as well. Im trying to achieve this through the ngOnChanges hook, as im using a detail component with no routing. This is what it looks like in code:

Movie component TS:

export class MoviesComponent implements OnInit {
  selectedP
  planets: any[];
  films: any[]
  constructor(private ms: MoviesService) { }

  ngOnInit(): void {
    this.ms.getPlanets()
      .subscribe(data => {
        this.planets = data;
        this.planets.map(m => this.films = m['films'])
      })

  }


  selectCharacter(caracter: any) {
    this.selectedP = caracter;
  }
}

Movie HTML

 <div class="col-md-3" *ngIf="planets">

            <ul class="list-group" *ngFor="let p of planets">
                <a
                class="list-group-item list-group-item-action"
                (click)="selectCharacter(p)"

                [class.active]="selectedP===p">
                    {{p.name}}
                </a>
            </ul>
        </div>
        <div class="col-md-6">
            <app-detail-no-routing [character]="selectedP" [films]="films"></app-detail-no-routing>
        </div>

The Service:

getPlanets(){
    return this.http.get('https://swapi.dev/api/people/')
    .pipe(map(p=>{
      let pl:any[]=p['results']
      return pl;
    }))
  }
  getCharacterMovies(url:string){
   return this.http.get(url)
  }
}

In the service the main method should be getPeople. Anyway, first I call the people endpoint which retrives an object with nested arrays, so I have the map operator to have a results array only, and that's what I subscribe in the component. And within that subscription I have a second map so I can have only the films array in which each character participates in. So far so good. I can render all the characters and I have the films array ready. Then I pass all of this through the Input decorator and I populate the arrays in the child component:

export class DetailNoRoutingComponent implements OnInit, OnChanges {
  @Input() character: any;
  @Input() films:any;
  value:any;
  url:any;
  participations:string[];
  constructor(private movieService:MoviesService) { }




  ngOnChanges(changes: SimpleChanges) {
    if (changes['character']) {
      this.value=changes['character']['currentValue']
      this.url=this.value['films']
      this.url.forEach((value)=> {
        this.movieService.getCharacterMovies(value).subscribe(data=>{
          this.participations=(data['title']);

            console.log(typeof this.participations)

        })
      });
    }
  }

HTML:

<h4 *ngIf="character">Movies participation</h4>
<p >{{participations}}</p>

So, as I click on a diferent character, I want to display the movies he has been into. As it is, I get only the last movie the character was in and the logs show me all the movies but as strings only, and if I iterate over them I get the chars...So there is something going on and I can't figure out what...Can someone give me a hint?

标签: angularinputngonchanges

解决方案


在 movie.component.ts 更改

ngOnInit(): void {
    this.ms.getPlanets()
      .subscribe(data => {
        this.planets = data;
        this.planets.map(m => this.films = m['films'])
      })

  }

ngOnInit(): void {
    this.ms.getPlanets()
      .subscribe(data => {
        this.planets = data;
        this.films = this.planets.map(m => m['films'])
      })

  }

并将您的 ngOnChanges 更改为:-

ngOnChanges(changes: SimpleChanges) {
    if (changes['character']) {
      this.value=changes['character']['currentValue']
      this.url=this.value['films']
      this.participations = [];
      this.url.forEach((value)=> {
        this.movieService.getCharacterMovies(value).subscribe(data=>{
          this.participations.push(data['title']);
            console.log(typeof this.participations)

        })
      });
    }
  }

推荐阅读