Tips on how child component can detect when the object passed from parent component has been updated in Angular

In the child component, I am receiving an object from the parent component that looks like this:

{
  attribute: 'aaaa',
  attribute2: [
    {
      value
    },
    {
      value
    },
    {
      value
    },
  ]
}

This object is passed to the child component as an @Input. When changes are made to the objects inside the attribute2 array, I want the child component to detect these changes and update accordingly. Since manipulating the object directly did not work, I ended up cloning the entire object in the parent component using (

this.object = _.cloneDeep(this.object)
) so that the child component can recognize the changes.

Is there a more efficient way to achieve this without having to clone the entire object? Thank you for your help!

EDIT:

Child Component

export class ChildComponent implements OnInit, OnChanges {
  @Input() public object: any;
}

html

<div>
   <span>{{object.attribute}}</span>
   <div *ngFor="let items of object.attribute2">{{item.value}}</div>
</div>

Parent Component

export class ParentComponent implements OnInit {
  public object: any;

  updateObject() {
      this.object.attribute2[1] = 'Changed value';
      this.object = _.cloneDeep(this.object);
  }
}

html

<div>
   <child-component [object]="object"></child-component>
</div>

Answer №1

Utilizing EventEmitter and service communication proves to be an effective method for triggering changes in the child component.

@Tony suggests using ngOnChanges() as a quick way to detect changes in bounded properties. However, relying on this hook can have long-term consequences as it will run every time any bound property changes, whether intentionally or not.

To demonstrate service-based communication, I have provided an example:

In this scenario, I bind an Array to the child component using @Input(), where new data additions update the array in the parent component. Subsequently, the latest value is passed through the service, which emits this value. The child component then subscribes to this value to execute relevant code.

The Service:

import { Injectable, EventEmitter } from '@angular/core';

@Injectable({
    providedIn: "root"
})
export class DataService {

  dataUpdated:EventEmitter<any> = new EventEmitter();

  constructor() { }

  setLatestData(data) {
    this.dataUpdated.emit(data);
  }

}

Child Component TS

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

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {

  @Input() allData: [];
  latestData: any;

  constructor(private dataService: DataService) { }

  ngOnInit() {
    this.dataService.dataUpdated.subscribe((data) => {
      this.latestData = data;
    });
  }

}

Child Component HTML

<p>
Latest Data: {{ latestData }}
</p>
<h3>List:</h3>
<li *ngFor="let data of allData">
  {{ data }}
</li>

Parent Component TS

import { Component } from '@angular/core';
import { DataService } from './data-service.service'

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';
  dataArr = [];

  constructor(private dataService: DataService){}

  onAddTimestamp() {
    let timestamp = new Date();
    this.dataArr.push(timestamp);
    this.dataService.setLatestData(timestamp);
  }

}

Parent Component HTML

<hello name="{{ name }}"></hello>
<p>
  Start editing to see some magic happen :)
</p>
<button
(click)="onAddTimestamp()"
>
  Add Timestamp
</button>
<app-child
[allData] = "dataArr"
></app-child>

Answer №2

Implementing the ngOnChanges() method within your component is crucial.

The ngOnChanges function is executed immediately after checking the data-bound properties, but before inspecting the view and content children if any changes are detected.

An example implementation could look like this:

@Input() item: string;

ngOnChanges(changes: SimpleChanges) {
    console.log(changes.item.currentValue);
    // You can access item.previousValue as well as
    // item.firstChange to compare old and new values
}

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

Having trouble with NextJS TypeScript and the randomUUID?() function? If you're seeing the error TS2386 that says "Overload signatures must all be

In my project setup, I have a mono-repo structure utilizing Lerna for managing 2 NextJS projects and 1 shared project. I recently attempted to integrate typescript. The NextJS projects seem to be functioning correctly (following the documentation), but I ...

Incorporate the Angular library into my project privately without the need to publish

I have developed an Angular library called My-lib and I want to integrate it into my application named My-app without publishing it to the NPM repository. I attempted to use the npm link command after building My-lib with npm link /folder/My-lib/dist/My-l ...

Utilizing Laravel's URL::asset method in conjunction with a JavaScript variable

Having a go at creating an HTML tag using the Jquery snippet below $("<option />",{ 'data-src':"{{ asset(my-javascript-variable) }}", id:'my_id').appendTo($('#image')); An option tag is being added to a select element. ...

What is the method for editing individual rows in a data table in Spring MVC when the edit button is clicked?

Every time I click on <a id="myBtn"><i class="fa fa-pencil" style="color:OliveDrab;"></i></a>, I only get a modal on the first row click, and it appears empty. I've searched through many internet resources, but none of them pro ...

Create a dynamic calendar by integrating dates with Javascript and an HTML table

Recently, I decided to delve into web design again and embark on a challenging project for my father's baseball business. The main task at hand is creating a detailed calendar using HTML tables. After spending a considerable amount of time perfecting ...

explore a nested named view using ui-router

My app has a view called mainContent. <div class = "wrapper" ui-view = "mainContent"> </div> There is only one route for this view. $stateProvider .state("home", { url: "/home", vi ...

The Angular service successfully provides a value, yet it fails to appear on the webpage

Currently, I am starting to dive into Angular from the ground up. One of my recent tasks involved creating a component called 'mylink' along with a corresponding service. In my attempt to retrieve a string value from the service using 'obse ...

What is the process for determining the estimated location of a queued event within a JavaScript Engine's event queue?

Imagine a multitude of events being created and added to the event queue of a Javascript engine. Are there any techniques or recommended practices in the industry to predict the order in which a specific event will be added to the queue? Any knowledge or ...

How to directly stream a Google Cloud Storage file into an fs.Readstream without the need to save it

Is there a way for me to send a video file directly from Google Cloud Storage to an API that only accepts fs filestreams without having to download and save the file locally first? I'm currently using the code below to send video files, but it require ...

Tips for sending information to a JavaScript variable through AJAX requests

Hello there, I'm currently working on a project that involves posting data stored in a JavaScript variable using AJAX. Can anyone assist me with the correct syntax for this process? <div class="container-fluid"> <div class="card shadow m ...

Exploring nested maps in JavaScript

I attempted to nest a map within another map and encountered an issue where the innermost map is being executed multiple times due to the outer map. The goal is to link each description to a corresponding URL (using # as placeholders for some links). Here ...

Using AJAX asynchronously in JavaScript commands synchronization

After researching similar questions on SO without finding a satisfactory answer, I encountered an issue with synchronous AJAX calls in my HTML/JavaScript page. Mozilla has deprecated some functionality related to synchronous requests, making it necessary f ...

What could be the reason for the failure of .simulate("mouseover") in a Jest / Enzyme test?

I have a scenario where a material-ui ListItem triggers the display of a material-ui Popper containing another ListItem on mouse over using the onMouseOver event. While this functionality works as expected, I am facing difficulties replicating the behavior ...

What is the most effective method for transferring items between arrays in JavaScript?

In my situation, I am dealing with two arrays - 'objects' and 'appliedObjects'. My goal is to find an elegant solution in Javascript and/or Angular for transferring objects from one array to another. Initially, my approach was as follo ...

Issue: React child must be a valid object - Runtime Error Detected

As I delve into the world of React, NextJs, and TypeScript, I stumbled upon a tutorial on creating a navbar inspired by the 'Strip' style menu. It has been quite a learning journey for me as a newbie in these technologies. After seeking help for ...

Injecting controllers and classes dynamically using AngularJS

I'm currently working on a dynamic widgets list where each widget is defined by its html, class, controller, and name. Some of these parameters may be empty based on the type of widget. These widgets are then loaded dynamically into <li> element ...

Tips for incorporating local storage into Angular applications

After successfully creating a table using Angular, I decided to incorporate a local storage feature. Despite my efforts, I'm struggling with implementing gsklee/ngStorage and gregory/angular-local-storage libraries into my existing code. Could someon ...

Update selection of dropdown menu upon clicking an image

Is there a way to update the select option value by clicking on an image? I have a dropdown list filled with dates from a database as well as two images, one for moving left and the other for moving right. When the left image is clicked, I want to show the ...

Is it considered acceptable in React for the value of one state to be determined by another state?

Consider this scenario: state1 tracks the mouseover of clientX and clientY, while state2 retrieves the value from state1 upon clicking. Is this implementation acceptable? const [move,setMove]=useState([]) const [click,setClick]=useState([]) useEffect(() ...

The values of the elements in the image array are null when not inside the

I need help converting an image into a Uint8Array for use in F5 steganography with the f5stego package. After trying to implement this, I encountered an issue where the imageArray contains all zeroes when printed outside the function, but inside it holds ...