`Unresponsiveness in updating bound property after change in Angular2 child property`

Having trouble with my custom directive and ngOnChanges() not firing when changing a child property of the input.

my.component.ts

import {Component} from 'angular2/core';
import {MyDirective} from './my.directive';

@Component({
    directives: [MyDirective],
    selector: 'my-component', 
    templateUrl: 'Template.html'
})

export class MyComponent {
    test: { one: string; } = { one: "1" }

    constructor( ) {
        this.test.one = "2";
    }
    clicked() {
        console.log("clicked");
        var test2: { one: string; } = { one :"3" };
        this.test = test2; // THIS WORKS - because I'm changing the entire object
        this.test.one = "4"; //THIS DOES NOT WORK - ngOnChanges is NOT fired=
    }
}

my.directive.ts

import {Directive, Input} from 'angular2/core';
import {OnChanges} from 'angular2/core';

@Directive({
    selector: '[my-directive]',
    inputs: ['test']
})

export class MyDirective implements OnChanges {
    test: { one: string; } = { one: "" }

    constructor() { }

    ngOnChanges(value) {
        console.log(value);
    }
}

template.html

<div (click)="clicked()"> Click to change </div>
<div my-directive [(test)]="test">

Looking for help on why ngOnChanges isn't firing in this scenario. Thanks!

Answer №1

It's important to note that Angular2 does not support deep comparison, only reference comparison, which is considered normal behavior. For more information on this limitation, refer to this issue: https://github.com/angular/angular/issues/6458.

However, there are some workarounds available to notify a directive when certain fields in an object have been updated.

  • Directly referencing the directive from the component:

    export class AppComponent {
      test: { one: string; } = { one: '1' }
      @ViewChild(MyDirective) viewChild:MyDirective;
    
      clicked() {
        this.test.one = '4';
        this.viewChild.testChanged(this.test);
      }
    }
    

    In this scenario, the testChanged method of the directive is explicitly called. You can see an example of this in action here: https://plnkr.co/edit/TvibzkWUKNxH6uGkL6mJ?p=preview.

  • Utilizing an event within a service:

    A specific service defines the testChanged event

    export class ChangeService {
      testChanged: EventEmitter;
    
      constructor() {
        this.testChanged = new EventEmitter();
      }
    }
    

    The component uses the service to trigger the testChanged event:

    export class AppComponent {
      constructor(service:ChangeService) {
        this.service = service;
      }
    
      clicked() {
        this.test.one = '4';
        this.service.testChanged.emit(this.test);
      }
    }
    

    The directive subscribes to the testChanged event to be notified of updates

    export class MyDirective implements OnChanges,OnInit {
      @Input()
      test: { one: string; } = { one: "" }
    
      constructor(service:ChangeService) {
        service.testChanged.subscribe(data => {
          console.log('test object updated!');
        });
      }
    }
    

I hope this provides some clarity on the subject, Thierry

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

Insert a blank row at the top of the grid in Wijmo for Angular 2

I am attempting to insert a new empty row at the start of the grid when an external button is clicked. The grid is displaying correctly. <wj-flex-grid #flex [itemsSource]="data" [isReadOnly]="true" [headersVisibility]="'Column' ...

Receiving distinct data from server with Ionic 2 promises

Utilizing ionic 2 RC0 with promises to retrieve data from the server, I am facing an issue where I consistently receive the same data in every request due to the nature of promises. Hence, my question is: How can I tackle this problem and ensure differen ...

A step-by-step guide on configuring data for aria's autocomplete feature

Currently, I am implementing aria autocomplete and facing an issue while trying to populate data from the server into the selection of aria autocomplete. I have tried setting the selected property of the aria autocomplete object, but it doesn't seem t ...

State management in React using hooks

Recently, I've been grappling with form validation while working on a signup form for my React app using Next.js. I've noticed that many sign up pages typically hide an "invalid" message until the user interacts with an input field. I attempted t ...

Error TS2322 occurs during compilation in Typescript when using ng.IPromise

Having some issues while using Angular 1.x with Typescript. Here is the code causing trouble: get(id): ng.IPromise<Server.MyItem> { return this.$http.get(`${this.baseAddress}/${id}`).then(d => d.data); } After compiling with tsc, I am encoun ...

Comparing the Calculation of CSS Selector Specificity: Class versus Elements [archived]

Closed. This question requires additional information for debugging purposes. It is not currently accepting answers. ...

Construct a string by combining the elements of a multi-dimensional array of children, organized into grouped

My task involves manipulating a complex, deeply nested array of nodes to create a specific query string structure. The desired format for the query string is as follows: (FULL_NAME="x" AND NOT(AGE="30" OR AGE="40" AND (ADDRESS ...

how to adjust the width of a window in React components

When attempting to adjust a number based on the window width in React, I encountered an issue where the width is only being set according to the first IF statement. Could there be something wrong with my code? Take a look below: const hasWindow = typeof ...

Which to choose, setInterval or rxjs interval?

Many discussions have taken place on this topic, but I am still unsure about which approach is best for my specific use case. I have a method that needs to be called every 3 seconds in order to receive updated stock details. ngOnInit() { this.getUpdat ...

When using Angular msal_angular in conjunction with an ASP.NET Core Web API, an error may occur indicating an invalid token

I developed my Angular application using the guide provided in this example: https://github.com/microsoftgraph/msgraph-training-angularspa Successfully, I managed to log in and authenticate with MS Graph from within the Angular app. However, I am facing ...

What is the best way to parse JSON data with Typescript?

I am dealing with JSON data structured as follows: jsonList= [ {name:'chennai', code:'maa'} {name:'delhi', code:'del'} .... .... .... {name:'salem', code:'che'} {name:'bengaluru' ...

Securing important code sections in Node/Express using Typescript: A guide

I'm fairly new to the world of JavaScript/Typescript/Node/Express, and as I've been researching, it seems there isn't a universally accepted method for locking critical sections of code in a Node/Express application. I've come across a ...

Unable to resolve all dependencies for UserService: (Http, ?)

After transitioning to the latest Angular2 version 2.0.0-beta.17, my project started experiencing issues. The structure of my UserService is as follows: import { Injectable} from '@angular/core'; import { Http } from '@angular/http'; ...

User interface designed for objects containing multiple keys of the same data type along with a distinct key

I have a question that relates to this topic: TypeScript: How to create an interface for an object with many keys of the same type and values of the same type?. My goal is to define an interface for an object that can have multiple optional keys, all of t ...

Experiencing a challenge while attempting to integrate AWS Textract with Angular using the aws-sdk/client-textract npm package. Despite my efforts, I keep encountering a Credentialerror

I have set up aws-sdk/client-textract in my app.component.ts file and specified the region for my Textract service. However, I am unsure of where to provide my access_key and secret_key, as well as what parameters need to be passed for Textract. If anyone ...

Angular Universal causes SASS imports to malfunction

Check out this sample app that you can download to see the issue in action: https://github.com/chrillewoodz/ng-boilerplate/tree/universal I am currently working on implementing angular universal, but I'm encountering an error with a SCSS import in o ...

Troubleshooting Angular HTTP: Issue with the HTTP request headers not updating

// assigning the httpclient protected _http: HttpClient = inject(HttpClient); // defining the options for the request const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/tcc' }), observe: 'resp ...

Ways to change a value into int8, int16, int32, uint8, uint16, or uint32

In TypeScript, the number variable is floating point by default. However, there are situations where it's necessary to restrict the variable to a specific size or type similar to other programming languages. For instance, types like int8, int16, int32 ...

Updating the DOM with an EventListener in Angular 5 is not functioning properly

Situation : Utilizing an Angular PWA for communication with an iOS native app via WKWebview. Implementing messageHandlers to facilitate data sharing between TypeScript and Swift logic code. Issue : Employing addEventListener to monitor a specific event on ...

Utilizing Angular to reference a computed variable in a different function while iterating through a loop

I recently started learning Angular 5 and coming from a background in PHP, I am finding variables a bit confusing. Currently, I am working on a loop where I want to use a calculated variable in another function within that same loop. Here is the code snip ...