How to transfer an object between sibling components in Angular 4

Being new to Angular 2+, I understand that I may not be approaching this the correct way. My issue involves two sibling components. When clicking on a "link" in one component, it redirects to another controller. My goal is to pass an object to the component that I am landing on.

This is my current approach:

In the first component (building list), I have an event:

public onClick_building(building: Building) {

  this._building.addBuilding(building);

  this._router.navigate(['/sam/checklistsam']);
}

The addBuilding method resides in a service called Building Service:

// Building Service

import { Injectable } from '@angular/core';
import { Headers, Http, RequestOptionsArgs, Response, ResponseContentType } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class BuildingService {

  public newBuildingIdSubject: Subject<Building> = new Subject<Building>();

  private _url = 'building/';

  constructor(private http: Http, private _server: ServerService) { }

  public addBuilding(building) {
    this.newBuildingIdSubject.next(building);
  }
}

Then, in the component (work with single building page) that I am redirected to:

// ChecklistComponent

import { Component, AfterViewInit, OnInit } from '@angular/core';

import { Building } from '../../../interfaces/building';

import { BuildingService } from '../../../services/building-service/building.service';
import { ServerService } from '../../../services/server-service/server.service';

@Component({
  selector: 'app-checklist',
  templateUrl: './checklist.component.html',
  styleUrls: ['./checklist.component.css'],
  providers: [BuildingService, ServerService]
})
export class ChecklistComponent implements AfterViewInit, OnInit {

  public building: Building;

  constructor(private _building: BuildingService) { }

  ngOnInit() {

    this._building.newBuildingIdSubject.subscribe(res => {
      this.building = res;
  });
}

However, 'this.building' is undefined. It seems like it doesn't enter the subscribe function during debugging.

Is there a better way to achieve this or am I overlooking something?

Thank you in advance!

Answer №1

There are a couple of issues that need to be addressed. Firstly, your shared service is not functioning as intended because it is not a singleton. By providing it in the providers array at the component level, you are creating separate instances of the service for each component.

In order to make the service a singleton, it should be added in the NgModule providers:

@NgModule({
  ...
  providers: [ BuildingService ] // like this!
})

Remove the service from the individual components as well as any similar services such as ServerService.

@Component({
  ...
  // providers: [BuildingService, ServerService] <-- Remove
})

The second problem arises from the use of a Subject, which does not behave as expected in this scenario. As next() needs to be called before navigating to the sibling component, the subscription in the sibling component will not receive the emitted value.

To resolve this issue, consider using a BehaviorSubject instead:

import {BehaviorSubject} from 'rxjs/BehaviorSubject';

public newBuildingIdSubject = new BehaviorSubject<Building>(null);

It's important to note that BehaviorSubject requires an initial value, so set this according to your specific requirements :)

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

What is the process of including items in an Array?

I have been attempting to use the push method to add elements to an Array in Typescript, but strangely it doesn't seem to be working. The array just stays empty. Here's the code I have: list: Array<int> = Array(10) for(le ...

Broaden the scope of a `Record<string, string[]>` by adding a new type of property

When working in Typescript, it appears that defining the type as shown below should create the desired outcome: interface RecordX extends Record<string, string[]> { id: string } However, an error is thrown stating: Property 'id' of t ...

What is the reason that property spreading is effective within Grid components but not in FormControl components?

Explore the sandbox environment here: https://codesandbox.io/s/agitated-ardinghelli-fnoj15?file=/src/temp4.tsx:0-1206. import { FormControl, FormControlProps, Grid, GridProps } from "@mui/material"; interface ICustomControlProps { gridProps?: ...

The Angular2 Router directs the user to the main Component

After configuring the Angular2 router and setting up the server (asp.net core) to redirect unknown paths to /index.html, the routing appears to be functioning properly. However, I am encountering an issue where visiting a specific URL (i.e. www.sitename.co ...

I require the ability to modify cellEditor parameters in real-time

How can a value be passed to cellEditorParams after the user double clicks on a grid row? The application triggers a service call on row click and the response needs to be sent to cellEditorParams. ...

Leverage process.env variables within your next.config.js file

Currently, I have an application running on NextJS deployed on GCP. As I set up Continuous Deployment (CD) for the application, I realized that there are three different deploy configurations - referred to as cd-one.yaml, cd-two.yaml, and cd-three.yaml. Ea ...

Performing a Protractor test on an Angular 5 application

We're in the process of transitioning our ui-library from AngularJS to Angular 5. I'm encountering challenges with the protractor tests. I need guidance on how to update the old AngularJS test to align it with Angular 5. If anyone has dealt wit ...

Disabling flow control to test an Angular app in Protractor results in an error being generated

I've been battling with this issue for quite some time now and my energy is running low. I am currently attempting to test an Angular application using protractor and async/await. The documentation suggests that I need to disable the control flow by a ...

Retrieve deeply nested array data using Angular service observable

My endpoint data is structured like this { 'dsco_st_license': { 'ttco_st_license': [ { 'csl_state': 'AK', 'csl_license_name': &ap ...

What is the best way to create a React component that renders a class component as a functional component?

My Objective: At the moment, I am in the process of developing an AuthUserRole HOC component to manage user roles like Manager and Employee. However, I encountered a tutorial that uses a functional component to return a class component as referenced here. ...

Is it possible to eliminate a parameter when the generic type 'T' is equal to 'void'?

In the code snippet below, I am attempting to specify the type of the resolve callback. Initially: Generic Approach export interface PromiseHandler<T> { resolve: (result: T) => void // <----- My query is about this line reject: (error: a ...

Angular Router automatically redirects to the base route from specific routes, but the issue is resolved upon refreshing the page

Have you ever experienced Angular Router redirecting the user back to the base url for certain routes? You might think it's an issue with the app-routing.module.ts file, but it gets even more bizarre. Anomaly #1 This strange behavior only occurs wh ...

Retrieve and showcase information from Firebase using Angular

I need to showcase some data stored in firebase on my HTML page with a specific database structure. I want to present the years as a clickable array and upon selecting a year, retrieve the corresponding records in my code. Although I managed to display a ...

Strange behavior of the .hasOwnProperty method

When attempting to instantiate Typescript objects from JSON data received over HTTP, I began considering using the for..in loop along with .hasOwnProperty(): class User { private name: string; private age: number; constructor(data: JSON) { ...

I am currently working on a project using the most up-to-date version of Angular, and I encountered an issue where the property 'value' is not recognized on the type 'EventTarget'

When utilizing the $event with the onkeyup event and attempting to pass the input field's value to the filter Function, it is not functioning as expected. <div class="container mx-auto p-5"> <div class="searchBar"> ...

Dynamic Variable Translation in Angular 8 using i18n

Within my app.component.html, there is a recurring element on every page: <h1 i18n="@@titleH1">{{title}}</h1> I created a shared service with setters and getters: ... title = new BehaviorSubject('Initial Title'); setTitle(title: s ...

The type 'any' cannot be assigned to the parameter type 'never' in this argument.ts

I received a warning: Argument of type 'any' is not assignable to parameter of type 'never'.ts(2345) Object is of type 'unknown'.ts(2571) Here is my request body: {"A":[{"filter":[{"a":"a"}]},{"group":[{"a":"a"}]}],"B":[{"f ...

Dynamically divide canvas screens based on fabricjs dropdown selection

I am attempting to implement split screens in fabric js, such as 1, 2, 4, 8, and 16. The screen should split based on the selection from the dropdown menu. Check out my current code where I have successfully uploaded images. If I click on the images, th ...

"Once the queryParams have been updated, the ActivatedRoute.queryParams event is triggered once

Within my Angular component, I am making an API call by passing a hash string extracted from the current query parameters. Upon receiving the API result, a new hash is also obtained and set as the new hash query parameter. Subsequently, the next API call w ...

Effortlessly bring in Typescript namespace from specific namespace/type NPM package within a mono-repository

Instead of repeatedly copying Typescript types from one project to another, I have created a private NPM package with all the shared types under a Typescript namespace. Each project installs this NPM package if it uses the shared types. index.d.ts export ...