Ayyash
Ayyash

Reputation: 4399

Angular2: Input setter not picking up set event if value does not change

Referring to Angular2 documentation file here: [https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#parent-to-child-setter] (Parent to child setter), I have the following child component code:

import { Component, Input } from '@angular/core';
@Component({
  selector: 'name-child',
  template: '<h3>"{{name}}"</h3>'
})
export class NameChildComponent {
  private _name = '';
  @Input()
  set name(name: string) {
    console.log("name change");
    this._name =  name;
  }
  get name(): string { return this._name; }
}

And the parent is simple:

import { Component } from '@angular/core';
@Component({
  selector: 'name-parent',
  template: `
  <h2>Parent </h2>
  <name-child [name]="name"></name-child>
  `
})
export class NameParentComponent {
   // somewhere on ngOnInit, set name without changing value
    ngOnInit() { 

        // get pending paged only and so on
        setTimeout(() => {
            this.name = "a";
            setTimeout(() => {
                this.name = "a";
                setTimeout(() => {
                    this.name = "a";
                },1000);

            },1000);

        },1000);
   }
}

You'd expect the console to log out "name change" three times in 3 seconds. It doesn't, it logs it once, and ignores subsequent sets (this happens only if the value does not change). How can I make the input pick up the set event, regardless of whether value changed or not?

Upvotes: 12

Views: 11509

Answers (4)

Naman Sharma
Naman Sharma

Reputation: 283

While yurzui's answer explains it enough, but if it's an Object you can use

let newObj = JSON.parse(JSON.stringify(oldObj))

it will trigger the setter event

Upvotes: 0

wickdninja
wickdninja

Reputation: 1039

Not positive if using the input setter is a strict requirement, but have you tried using OnChanges?

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
@Component({
  selector: 'name-child',
  template: '<h3>"{{name}}"</h3>'
})
export class NameChildComponent implements OnChanges {
  @Input() name;

  ngOnChanges(changes: SimpleChanges) {
    if (changes['name']) {
      console.log(`Is First Change: ${changes['name'].isFirstChange}`)
      console.log(`name change from ${changes['name'].previousValue} to ${changes['name'].currentValue}`);
    }
  }

}

Upvotes: 1

smnbbrv
smnbbrv

Reputation: 24541

The article you give explicitly says

Intercept input property changes with a setter

when what you are trying to achieve is not about tracking changes at all. It is about sending an event from parent to child and this is where RX Subject (any of 4 of them) or Angular2 EventEmitter is really good.

You can create one of them in the parent and pass it to the child. Then, after you subscribe to it, you can track all the events regardless of the value.

Upvotes: 4

yurzui
yurzui

Reputation: 214047

I see two ways to solve it:

1) Use immutable value

setTimeout(() => {
  this.name = new String("a");
    setTimeout(() => {
      this.name =  new String("a");
      setTimeout(() => {
       this.name =  new String("a");
    }, 1000);
  }, 1000);
}, 1000);

2) Change input property directly

@ViewChild(NameChildComponent) child: NameChildComponent;

setTimeout(() => {
  this.child.name = "a";
  setTimeout(() => {
    this.child.name = "a";
    setTimeout(() => {
      this.child.name = "a";
    }, 1000);
  }, 1000);
}, 1000);

Upvotes: 10

Related Questions