How to assign Angular @Input value into another variable and populate into the child?

Viewed 1722

I have following parent html

<p>Parent</p>
<app-child [mainData]="mainData"></app-child>

parent.ts

mainData = [];
ngOnInit() { 
 this.myService((res)=>{
 this.mainData = res;
})
}

Child html

<p>My JSON {{mainData | json}}</p> //Here getting result from parent

child.ts

@Input() mainData = [];
myDataCopy = [];
ngOnInit() { 
   this.myDataCopy = this.mainData; 
   console.log('My copy Data', this.myDataCopy); // Doesn't get result on here 
}

If I need to process the @Input data how it possible?

4 Answers

Try it in ngOnChanges lifecycle hook

child.ts

ngOnChanges(changes: SimpleChanges) {
  const mainDataChange = changes.mainData ;

  if (mainDataChange) {
    this.myDataCopy = this.mainData; 
    // or, this.myDataCopy = mainDataChange.currentValue;
    console.log('My copy Data', this.myDataCopy);
  }
}

You can try @Input getter and setter

  _mainData: any;
  @Input()
  set mainData( val ) {
    this._mainData = val;
  }

  get mainData: any {
    return this._mainData;
  }

And read more Here

Maybe syntax depend on Angular version...

Can you try to force "bindingPropertyName" argument in @Input declaration ?

like :

@Input('mainData') mainData = [];

Just to throw another alternative out there taken from this blog.

Stackblitz

export class ChildComponent implements OnChanges  {
  /* METHOD THREE 
   * Using a decorator
  */
  @OnChange<number>((value, simpleChange) => {
    console.log('OnChange decorator methodThree', value)
  })
  @Input()
  methodThree: number;

}

Decorator

export interface SimpleChange<T> {
  firstChange: boolean;
  previousValue: T;
  currentValue: T;
  isFirstChange: () => boolean;
}

export function OnChange<T = any>(callback: (value: T, simpleChange?: SimpleChange<T>) => void) {
  const cachedValueKey = Symbol();
  const isFirstChangeKey = Symbol();
  return (target: any, key: PropertyKey) => {
    Object.defineProperty(target, key, {
      set: function (value) {
        // change status of "isFirstChange"
        if (this[isFirstChangeKey] === undefined) {
          this[isFirstChangeKey] = true;
        } else {
          this[isFirstChangeKey] = false;
        }
        // No operation if new value is same as old value
        if (!this[isFirstChangeKey] && this[cachedValueKey] === value) {
          return;
        }
        const oldValue = this[cachedValueKey];
        this[cachedValueKey] = value;
        const simpleChange: SimpleChange<T> = {
          firstChange: this[isFirstChangeKey],
          previousValue: oldValue,
          currentValue: this[cachedValueKey],
          isFirstChange: () => this[isFirstChangeKey],
        };
        callback.call(this, this[cachedValueKey], simpleChange);
      },
      get: function () {
        return this[cachedValueKey];
      },
    });
  };
}

This method uses a typescript decorator. IMHO decorators are likely to stay but...

Decorator are an experimental feature that may change in future releases

Related