The classic pattern for data access in Angular suggests code like this:
Classic Data Access Pattern
getProducts(): Observable<Product[]> {
return this.http.get<Product[]>(this.productsUrl)
.pipe(
tap(data => console.log(JSON.stringify(data))),
catchError(this.handleError)
);
Above we have a method the returns an Observable. When the data is returned from the http endpoint, that Observable emits the data in a shape defined by the Product[]
generic parameter where Product
is an interface.
For a more reactive application, the declarative/reactive approach is often suggested. It changes the above method to a property declaration like this:
Reactive Data Access Pattern
products$ = this.http.get<Product[]>(this.url)
.pipe(
tap(data => console.log(JSON.stringify(data))),
catchError(this.handleError)
);
Notice that this declares a property in the service for the Observable instead of a method. The $
suffix on products$
is a convention used to distinguish properties that are Observables vs other types of data structures such as general objects or arrays.
This pattern is often used when there is UI interactivity (such as filtering based on a selection), when working with complex data (such as combining data from multiple end points) and when sharing data across components (such as when each component needs to react when the data changes).
The reactive data access pattern presents a common problem. How do we "pass" data required by the URL when using this technique?
For example, say that the http request requires a category to only pull down products for that category:
this.http.get<Product[]>(`${this.url}?cat=${catId}`)
How can this category be "passed in" since there is no method?
How to pass data in angular route component 1 Navigation within the application. ... 2 Using a state object of navigate () the method of Angular router object to pass data between components: Angular allows different ways of passing data between components. ... 3 Reading state object data in navigate () method. ... 4 Using Route params. ...
Angular provides two approaches to retrieve query params at the navigate component. You can read the query parameter from the activatedroute snapshot
The Angular Router will pass the { id:'1', name:"Angular"} when the StaticComponent is rendered. The data value will be located in the data property of the ActivatedRoute service. We can then read the data by subscribing to the activatedroute.data property as shown below.
This directive can be applied to any element, although it is typically applied to button and anchor elements Angular allows different ways of passing data between components. We will first learn and demonstrate the state object of navigate () method, this support came since the release of Angular 7.2.
Instead of thinking how to "pass" data, think instead about how to "emit" that value over time. To emit data, we define our own Observable using Subject
or BehaviorSubject
.
private categorySubject = new Subject<number>();
categorySelectedAction$ = this.categorySubject.asObservable();
products$ = this.categorySelectedAction$.pipe(
switchMap(catId=>this.http.get<Product[]>(`${this.url}?cat=${catId}`))
.pipe(
tap(data => console.log(data)),
catchError(this.handleError)
));
selectedCategoryChanged(categoryId: number): void {
this.categorySubject.next(categoryId);
}
In the above code, we define our Observable using a Subject
. We declare the Subject private so it cannot be accessed from outside our service. We then expose the read-only part of that Subject using asObservable()
.
Whenever the user selects a different category, the component calls selectedCategoryChanged
which emits the selected categoryId into the stream defined by our Subject.
For products$
, when a value is emitted, it is piped through a set of operators. The switchMap
is a higher-order mapping operator that automatically subscribes to the inner Observable (the this.http.get...
) and flattens the result. The returned products for the specified category are then emitted into the products$
stream.
To see a more complete solution, see this github: https://github.com/DeborahK/Angular-RxJS/tree/master/APM-Final
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With