D
D
danilr2019-03-30 21:07:22
Angular
danilr, 2019-03-30 21:07:22

What is the correct way to pass data through Angular service?

I'm taking my first steps in Angular 7, moving from Vue and it's a bit difficult to understand how everything is done here.
There are two components - search and result. In search, I enter data for the search (string), and in result I want to get this data. Help how to do it?
Root Component

<search></search>
<result></result>

search component
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 component
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);
      }
    )
  }
}

Service
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)
    }
}

well, if you need a search template
<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>

Answer the question

In order to leave comments, you need to log in

2 answer(s)
D
Demian Smith, 2019-04-01
@search

There is a best practice for your case: so-called smart and dumb components: https : //medium.com/@dan_abramov/smart-and-dumb-com...
In our case, the search and result components are stupid components that do nothing but return an input string (search) and display data (result). We also have a smart searchResults component that knows how to react to the data from search and render the result properly.
Search and Result don't need to know anything about the HttpService. It doesn't inject into them.
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;
        })
    }
}

Using services to pass data between components in Angular is the most common rake in the framework. Moreover, this rake is so cunning that most programmers do not even understand what is walking on them. The surest way not to step on a rake is to forget about private and public variables in services forever (in other words, the service should not have a state). Without this, you can live and, moreover, easily and calmly if you start using NxRx to store the state of the system.

D
Denis, 2019-03-30
@sidni

You were answered this question in a comment even with the code
How to make API requests in Angular 7?
Just read passing data through a service like https://medium.com/@weswhite/angular-behaviorsubje...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question