@danilr

Как правильно передавать данные через сервис Angular?

Делаю первые шаги в Angular 7, перехожу с Vue и сложновато как-то пока понимать как тут все делается.
Есть два компонента - search и result. В search я ввожу данные для поиска(string), а в result хочу получить эти данные. Помогите как это сделать?
Корневой компонент
<search></search>
<result></result>

search компонент
import { Component, OnInit, Input, EventEmitter, Output, OnChanges} from '@angular/core';
import { getRenderedText } from '@angular/core/src/render3';
import { HttpService } from '../http.service'

@Component({
  selector: 'search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.scss']
})

export class SearchComponent{
  film: string;
  films: any;

  constructor(private httpService: HttpService){}

  handlerEnterSearch(){
    this.httpService.setInputFilm(this.film)
  }
  ngOnInit(){}
}

result компонент
import { Component, OnInit } from '@angular/core';
import { HttpService } from '../http.service'

@Component({
  selector: 'result',
  templateUrl: './result.component.html',
  styleUrls: ['./result.component.scss']
})
export class ResultComponent implements OnInit {

  films:any;

  constructor(private httpService: HttpService){

  }

  ngOnInit() {
    this.httpService.getFilms().subscribe(
      data => {
        this.films = data;
        console.log('data: ', data);
      }
    )
  }
}

Сервис
import {Injectable} from '@angular/core';
import {EventEmitter} from '@angular/core';
import {HttpClient,HttpParams} from '@angular/common/http';
import {Observable} from 'rxjs';
import { map } from 'rxjs/operators';
  
@Injectable()
export class HttpService{
    baseURL: string = "https://api.themoviedb.org/3";
  searchURL: string = "/search/movie"
  inputFilm: string
    newFilms:EventEmitter<any> = new EventEmitter();

    constructor(private http: HttpClient){ }

    setInputFilm(inputFilm:string){
        this.inputFilm = inputFilm
        console.log('this.inputFilm: ', this.inputFilm);
    }
    getFilms(){
        const params = new HttpParams().set('api_key', 'd6a5ac2d3d7cab11a084ca8080421b20').set('query', this.inputFilm)
        const options = {params: params};
        return this.http.get(this.baseURL+this.searchURL, options)
    }
}

ну и если нужен шаблон search
<div class="input-group input-group-lg p-5">
      <input
        [(ngModel)]="film"
        type="text"
        class="form-control"
        placeholder="Что ищем?"
        (keyup.enter)="handlerEnterSearch()"
      >
      <div class="input-group-append">
        <button class="btn btn-primary" type="button" (click)="handlerEnterSearch()">Найти фильм</button>
      </div>
    </div>
  • Вопрос задан
  • 3393 просмотра
Пригласить эксперта
Ответы на вопрос 2
search
@search
мама говорит что я особенный
Для вашего случая существует лучшая практика: так называемые умные и глупые компоненты: https://medium.com/@dan_abramov/smart-and-dumb-com... (это оригинальная статья от автора реакта, но в ангуляре принципы такие же)

В нашем случае компоненты search и result - глупые компоненты, которые только и делают, что возвращают строку ввода (search) и отображают данные (result). Так же у нас имеется умный компонент searchResults, который знает как отреагировать на данные из search и правильно отобразить result.

Search и Result ничего не должны знать об HttpService. Он в них не инжектится.

SearchComponent:

import { Component, EventEmitter, Output } from '@angular/core';

@Component({
    selector: 'search',
    templateUrl: './result.component.html',
    styleUrls: ['./result.component.scss']
})
export class SearchComponent {

    public query: string;

    @Output() onQuery: EventEmitter<string> = new EventEmitter();

    constructor() {}

    public handlerEnterSearch() {
        this.onQuery.emit(this.query)
    }
}


search.html:

<div class="input-group input-group-lg p-5">
    <input
        [(ngModel)]="query"
        type="text"
        class="form-control"
        placeholder="Что ищем?"
        (keyup.enter)="handlerEnterSearch()"
    >
    <div class="input-group-append">
        <button class="btn btn-primary" type="button" (click)="handlerEnterSearch()">Найти фильм</button>
    </div>
</div>


result.component.ts

import { Component, OnInit, Input } from '@angular/core';
import { HttpService } from '../http.service'

@Component({
  selector: 'result',
  templateUrl: './result.component.html',
  styleUrls: ['./result.component.scss']
})
export class ResultComponent implements OnInit {

  // Вот эти items выводятся в html результата
  @Input()
  items: any[];

  constructor(){}
}


search-result.html:

<search (onQuery)="doSearch($event)">
<result [items]="result">


search-result.component.ts:

import { Component, OnInit } from '@angular/core';
import { HttpService } from '../http.service'

@Component({
    selector: 'search-result',
    templateUrl: './search-result.component.html',
    styleUrls: ['./search-result.component.scss']
})
export class SearchResultComponent implements OnInit {

    items:any[];

    constructor(private httpService: HttpService){

    }

    // Вот это неудачная часть. Её можно сделать веселее, но для этого необходимо понимать как устроен RxJS.
    // Я не знаю как это объяснить без написания отдельной статьи.
    // На первое время такой подход сойдёт.
    doSearch(query: string) {
        this.httpService.getFilms(query).subscribe((items) => {
          this.items = items;
        })
    }
}


Использование сервисов для передачи данных между компонентами в ангуляре - это самые распространённые грабли во фреймворке. Причём эти грабли настолько хитрые, что большинство программистов даже не понимает что ходит по ним. Самый верный способ не наступать на грабли - это забыть навсегда про private и public переменные в сервисах (другими словами сервис не должен иметь состояние). Без этого можно жить и причём легко и спокойно если начать использовать NxRx для хранения состояния системы.
Ответ написан
@sidni
Php Developer
Вам же ответили на этот вопрос в комментарии даже с кодом
Как правильно делать запросы к API в ангуляр 7?
Только прочитайте передача данных через сервис типа https://medium.com/@weswhite/angular-behaviorsubje...
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы