Swap references between two components at the same level

There are two instances of custom-component spawned by a shared parent with distinct data, each displayed as a tab in the mat-tab-group.

<mat-tab-group>
  <mat-tab label="TAB1">
    <ng-template matTabContent>
      <custom-component [data]="tab1data"></custom-component>
    </ng-template>
  </mat-tab>
  <mat-tab label="TAB2">
    <ng-template matTabContent>
      <custom-component [data]="tab2data"></custom-component>
    </ng-template>
  </mat-tab>
</mat-tab-group>

The data attribute is utilized to set the internal _data which is then enclosed within MatTableDataSource:

@Input()
set data(val: Data[]) {
    this._data = val;
    this.loadData();
}

loadData(): void {
    this.dataSource = new MatTableDataSource<Data>(this._data);
    this.dataSource.sort = this.sort;
}

In certain scenarios, actions performed on the component within the first tab must impact the data displayed in the second tab. Is there a method to share references between components so that I can modify _data and initiate loadData() from another component?

Answer №1

If you're looking to establish communication between two components in Angular, RxJS observables can come in handy.

For a practical demonstration on how this can be achieved, check out this StackBlitz example: https://stackblitz.com/edit/angular-ivy-myr2kh

my-service.service.ts

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable()
export class MyServiceService {
  private dataChangeObservable = new Subject<any>();
    dataChangeStream = this.dataChangeObservable.asObservable();

  constructor() { }

  emitDataChange() {
    this.dataChangeObservable.next();
  }
}

ComponentOne.component.ts

onclickDiv() {
    this.myService.emitDataChange(); // This triggers the change event
}

ComponentTwo.component.ts

ngOnInit() {
    this.dataChangeSubscription$ = this.myService.dataChangeStream.subscribe(() => {
       this.count++; // This listens for and responds to the change event
    })
 }

Update

In scenarios where you have multiple instances of the same component, you'll need to identify which instance should receive updates.

Take a look at this modified example: https://stackblitz.com/edit/angular-ivy-4pznor

In your parent HTML:

<app-componentone [name]="'one'"></app-componentone>
<app-componentone [name]="'two'"></app-componentone>

Here, 'one' and 'two' are passed as inputs to distinguish between different instances.

Then, in your TypeScript file:

import { Component, OnInit, Input } from '@angular/core';
import { MyServiceService } from '../my-service.service';

@Component({
   selector: 'app-componentone',
   templateUrl: './componentone.component.html',
   styleUrls: ['./componentone.component.css']
})
export class ComponentoneComponent implements OnInit {
  @Input() name; // Stores the instance name
  count = 0;
  
  constructor(
     private myService: MyServiceService
  ) { }

  ngOnInit() {
    this.myService.dataChangeStream.subscribe((value) => { 
      if (this.name !== value) { 
         this.count++;
      }
    })
  }

  onclickDiv() {
    this.myService.emitDataChange(this.name); // Passes the instance name to trigger updates on specific components
  }
}

Answer №2

Communication between tabs can be achieved by emitting an output event from the first tab to its parent component.

Within the Custom Component, define an output event like this:

@Output() public dataChange = new EventEmitter();

To emit this event when the data changes, use the following code:

this.dataChange.emit('changed data');

In the parent component where the selector of the Custom Component is used, adjust the selector as follows:

HTML :-

<custom-component [data]="tab1data" (dataChange)="modifyDataTab2($event)"></custom-component>

TS :-

modifyDataTab2(firstTabData) {
   this.tab2Data = firstTabData;
   // additional modifications can be made here
} 

By setting up the communication in this way, any changes in tab2Data will automatically trigger the execution of loadData(). This approach eliminates the need to modify the Custom Component each time data needs to be changed between tabs.

If you want to update the data on tab1 based on changes on tab2, simply make adjustments in the parent component:

HTML :-

<custom-component [data]="tab2data" (dataChange)="modifyDataTab1($event)"></custom-component>

TS :-

modifyDataTab1(secondTabData) {
   this.tab1Data = secondTabData;
   // additional modifications can be made here
} 

Utilizing a common parent component for communication ensures that any changes in shared data are efficiently propagated between child components without the need for direct communication between them.

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

Anticipate receiving a 'Type' returned by external library functions

I've recently started learning TypeScript and have encountered a situation where I need to assign a type to a variable that is returned from a third-party library function with its own type definition. For instance: import {omit} from 'lodash&ap ...

Is there a way to assign API data as inner HTML using Lit?

Need help setting inner html of html elements with a get request Any suggestions on how to achieve this? import { LitElement, html, css } from "lit"; import { customElement } from "lit/decorators.js"; import axios from "axios" ...

Struggling to locate the module in React Native with TypeScript configuration

Currently, I am in the middle of transitioning our react-native project from JavaScript to TypeScript. As I attempt to import old modules, I keep encountering the following error: Cannot find module 'numeral' Oddly enough, the 'numeral&apo ...

How to ensure Service is loaded before App Component in Angular 6?

My Data service is responsible for fetching the JSON Object value, however all components load before the data service finishes loading. This results in undefined values when I call the service method from components. ...

What is preventing me from adjusting the padding of the mat-button?

Trying to adjust the default padding of a mat-button, but encountering issues with changing the component's style. Any suggestions on how to subscribe to the default padding (16px)? I've attempted modifying CSS properties to set the padding of a ...

Error: Attempting to access a property called 'sign' on an undefined value

I encountered an issue while signing my transaction where I received an error message stating sendTransaction needs signer. Even though both message (encrypted using keccak256) and signer have values, I am unsure why there is a problem when executing the w ...

Issue with decorators not functioning in the latest alpha version of Sequelize v7

As I was exploring sequelize v7 (alpha), I encountered multiple errors when trying out basic examples directly from their documentation. For instance, taken straight from the official documentation import { Sequelize, DataTypes, Model, InferAttributes, Inf ...

Is it possible for me to add a string to a URL as long as the string is not null?

When retrieving data from a database, I have the option to include specific parts for a more targeted search. Let's say I have an object structured like this: { title: "wonderland", aliases: "", ... } My goal now is to generate a URL for the ...

Tips for overlaying a webpage with several Angular components using an element for disabling user interactions

I currently have an asp.net core Angular SPA that is structured with a header menu and footer components always visible while the middle section serves as the main "page" - comprised of another angular component. What I am looking to achieve is ...

Tips for effectively sending prop to a component in React with the help of TypeScript

Hey there, I'm working on a component called FormField which can accept either an icon for create or edit. Currently, I am using this FormField inside another component called SelectWithFormField. Here's how it looks: const FormField = ({create, ...

Showing object data in TypeScript HTML when the object property starts with a numeral

Below is the function found in the TypeScript file that retrieves data from an API: .ts file getMachineConfigsByid(id) { this.machinesService.getMachineConfigById(id).subscribe((res) => { if (res.status === 'success') { ...

`Typescript does not adhere to the specified type when used inside a for loop with a local

This code snippet declares a variable venuelist of type Venue array and initializes it as an empty array. The type Venue has a property named neighborhood. There is a for loop that iterates through the venuelist array and checks if the neighborhoods matc ...

Can you identify the specific error type that occurs in the onError function of react-query's MutationCache when using Typescript

Can someone help me with identifying the type of error in react-query MutationCache onError function when using Typescript? I also need guidance on how to override the type so that I can access and use the fullMessage from the data. const queryClient = new ...

Using XML in Angular for POST requests

I am currently working with Angular (not AngularJS) and have a web service that uses SOAP to interact with XML data. Although I've searched extensively, I haven't been able to find a comprehensive example of a POST request using XML. If anyone ...

I prefer the value to switch to false whenever I navigate to a new route and then return to the previous route, as the sidebar remains open

click here for image details view image description here Struggling to set the value as false when revisiting this site. Need assistance! Could someone lend a hand, please? ...

Create an abstract method that will return the properties of the constructor

To establish an abstract class in typescript, we can name it Entity, which contains an abstract method called constructorProps() that returns the array of properties required to build the derived class. For instance, if Foo extends Entity and does not hav ...

Setting up ReactJS and TypeScript in a fresh MVC5 project from scratch

After extensively trying out various tutorials, I have yet to successfully run a basic MVC5 project using TypeScript and ReactJS. For reference, I have created these projects from scratch in Visual Studio 2015 with .NET 4.6.1, using the ASP.NET Web Applic ...

Leveraging NgRx for Managing Arrays

export class Ingredient { public name: string; public amount: number; constructor(name: string, amount: number) { this.name = name; this.amount = amount; } } List of Ingredients: export const initialIngredients: Ingredient ...

What is the best way to assign unique IDs to automatically generated buttons in Angular?

Displayed below is a snippet of source code from an IONIC page dedicated to shapes and their information. Each shape on the page has two buttons associated with it: shape-properties-button and material-information-button. Is it possible to assign different ...

Reusing methods in Javascript to create child instances without causing circular dependencies

abstract class Fruit { private children: Fruit[] = []; addChild(child: Fruit) { this.children.push(child); } } // Separate files for each subclass // apple.ts class Apple extends Fruit { } // banana.ts class Banana extends Fruit { } ...