Answer the question
In order to leave comments, you need to log in
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>
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(){}
}
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)
}
}
<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
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)
}
}
<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>
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 (onQuery)="doSearch($event)">
<result [items]="result">
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;
})
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question