Strategies for mitigating the use of Observables when passing data between Angular routes

When trying to exchange data between routes, the most effective method appears to be using a service. To ensure that data is updated and re-rendered in the view, we are required to utilize BehaviorSubject.

Based on my understanding, a simple component would look something like this:

@Component({
    selector: 'user-info',
    template: `
        {{($user | async).firstName}}
        <button (click)="updateName()"></button>
    `
})
export class UserInfoComponent {

    private $user;
    private subscribe;

    constructor(private service: UserService) {
        this.user$ = this.service.get();
    }

    updateName() {
        this.subscribe = this.service.get().subscribe(user => 
            this.service.update({...user, firstName: 'new-name'})
        );
    }

    ngOnDestroy() {
        this.subscribe.unsubscribe();
    }
}

This process may seem cumbersome because if router wasn't involved, we could simply call the component with

<user-info [user]="user | async"></user-info>
, making it much cleaner:

@Component({
    selector: 'user-info',
    template: `
        {{user.lastName}}
        <button (click)="updateName()"></button>
    `
})
export class UserInfo2Component {

    @Input() user: User;

    constructor(private service: UserService) {}

    updateName() {
        this.service.update({...user, lastName: 'new-name'});
    }
}

Therefore, my question remains: Why is sharing data between routes so challenging? Is there possibly a more efficient solution that I have overlooked?

Answer №1

One common mistake is handling the update logic within components instead of in the service.

Consider this alternative approach:

User Service

import { Component, Input } from '@angular/core';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';

export class UserService {
  private user = new BehaviorSubject({
    firstName: 'Tomasz'
  })

  user$ = this.user.asObservable();

  update(user: any) {
    this.user.next({
      ...this.user.getValue(),
      ...user
    })
  }
}

App Component.ts

import { Component } from '@angular/core';
import {UserService} from './user.service';

@Component({
  selector: 'my-app',
  template: `
  <input (keydown.enter)="updateUser(input.value); input.value=''" #input>

  {{ user$ | async | json }}
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  user$;

  constructor(private userService: UserService) {
    this.user$ = this.userService.user$;
  }

  updateUser(firstName: string) {
    this.userService.update({ firstName });
  }
}

Check out the live demo here!

Answer №2

If you want to avoid using observables, consider implementing ngrx. This approach is built on the foundation of the redux concept.

By setting up data in the store and passing an ID in your route, you can easily retrieve data from the store in the next route. Since the store serves as the single source of data, there's no need to continuously pass data between routes. Each route can simply set data in the store, allowing other routes to access it when needed.

To explore this further, check out: Why use NGRX instead of constructor injected services with observables?

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Enhancing the loading speed of hefty Angular components

The issue I encountered involved a large component that loads over 1000 data elements, populated by a service called only once. Initially, the service was being called each time the component initialized, which seemed to be causing performance problems. To ...

Creating a new list by grouping elements from an existing list

I have successfully received data from my API in the following format: [ {grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1"}, {grade: "Grade B", id: 2, ifsGrade: &quo ...

Guide on deploying multiple applications under a single URL with S3 on Amazon Web Services

I am working on deploying multiple Angular and React apps on AWS through S3. Currently, one of my Angular apps is successfully running when accessing mysite.com. It functions properly as intended. I am looking for a way to load different apps based on th ...

Setting up a routerLink from a component

My current routing is functioning well, however, I am interested in managing the same functionality from a component rather than directly in the HTML. How can I achieve this? HTML <a [routerLink]="[ '..', card.item ]">VIEW MORE</a> ...

The element 'commit' cannot be found within the property

I am facing an issue when transitioning from using Vuex in JavaScript to TypeScript. The error message Property 'commit' does not exist appears in Vuex's mutations: const mutations = { methodA (): none { this.commit('methodB' ...

Upgrade from AngularJS 1.x to the latest version of Angular, AngularJS 2.x

Currently in the process of mastering AngularJS 2 in order to transition my applications from Angular 1.x. The differences between the two versions are quite significant. Can you please share the advantages of upgrading from Angular 1 to Angular 2? I am ...

Enhance the functionality of angular-material buttons by incorporating dynamic loading animations into

I am currently working on a solution in Angular 12 to disable a button (and show a spinner) when it is clicked, until the API responds. To achieve this, I plan to follow a similar approach to the angular-material button implementation. Essentially, I want ...

What is the best way to access a component's data within its method using Vue and Typescript?

Starting a Vue.js project with TypeScript and using single file components instead of class-styled ones has been my goal. However, I have encountered a recurring issue where I get error TS2339 when trying to reference my components' data using the "th ...

Move the vertex onto the mxGraph canvas using drag-and-drop functionality

Hey there, I'm currently working on dragging and dropping a vertex from the create button onto the mxGraph canvas, similar to how it's done in draw.io. This is what my TS code looks like: addShape(shape: string,event) { event.stopPropagation(); ...

What is the best way to dynamically update styleUrls or style properties in Angular?

One of my goals is to give users the ability to customize colors and certain styles within my Angular application. I am thinking about creating a structure like this: Structure: component-one   folder-with-css-files     style-for-component-1-fo ...

The function Interceptor.intercept is not defined

For a while now, I've been working on implementing an application-wide interceptor. However, no matter what I do, I keep encountering the same frustrating error: TypeError: this.interceptor.intercept is not a function After countless hours of debugg ...

Prisma auto-generating types that were not declared in my code

When working with a many-to-many relationship between Post and Upload in Prisma, I encountered an issue where Prisma was assigning the type 'never' to upload.posts. This prevented me from querying the relationship I needed. It seems unclear why P ...

The Angular Material Table experienced a collapse when trying to render over 20 columns simultaneously

Currently, I am experiencing an issue in Angular Version 5 where the Angular Material Table collapses when rendering more than 20 columns. Here is a snapshot of what my table looks like: https://i.stack.imgur.com/MXfvQ.png https://i.stack.imgur.com/XHWgq ...

I am struggling to save the value from my input field into the app.component.ts file

Having some trouble storing an input from my form into a property. After submitting, the console.log is showing undefined in the console. I've experimented with different variations, but none seem to be working as intended. <form> <input #i ...

Steps to create a formGroup in Angular 12

import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-signup', templateUrl: './signup.component.html', ...

Injecting the OrderEntry context into the CartOutlets.ITEM_DETAILS outlet in Spartacus can be achieved by following these

Here is a question from a different source: Is there a way to access orderEntry while utilizing <ng-template [cxOutlet]="CartOutlets.ITEM_DETAILS"> </ng-template> placeholder from the cart-item component? It appears that without [c ...

When uploading from Angular 2, PHP fails to populate the $_POST and $_FILES variables

I'm encountering difficulties when trying to upload files and data to my server using Angular 2 and PHP. After following the instructions in File Upload In Angular 2? to upload data and files from Angular 2, everything appears to be functioning corre ...

Navigating the pathway to retrieving variables within an Angular Component function

export class MapsComponent implements OnInit { @ViewChild('googleMap') gmapElement: any; map: google.maps.Map; data = "initialised"; ngOnInit() { var directionsService = new google.maps.DirectionsService; ...

Using the Ternary Operator in JavaScript to Dynamically Update HTML Elements with Angular

Is there a way to convert the code below into a ternary operator so that it can be used in an .HTML file? statusChange && statusChange === 'Employed' ? true : employmentStatus === 'Employed'; To clarify, I want to assign the re ...

How can I dynamically set the selected index in Nebular's nb-stepper using code?

Currently, I am testing out the nb-stepper component and wanted to configure the selectedIndex in my Angular component. However, when I try to apply two-way binding on [(selectedIndex)] and refresh my activities, the nb-step does not update to display the ...