Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to "pass" data when using a declarative/reactive data access approach with RxJS in Angular?

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?

like image 410
DeborahK Avatar asked Jul 24 '21 00:07

DeborahK


People also ask

How to pass data in angular route component?

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. ...

How to retrieve query parameters at the navigate component in angular?

Angular provides two approaches to retrieve query params at the navigate component. You can read the query parameter from the activatedroute snapshot

How to read the data from a static component in angular?

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.

What is the use of navigate directive in angular?

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.


1 Answers

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

like image 120
DeborahK Avatar answered Oct 18 '22 07:10

DeborahK