Search code examples
javascriptangulartypescriptparameter-passingpass-by-value

How to pass object by value into Angular2+ component


Let's say I have a component that takes in a Foo instance and displays a form to edit it.

export class ChildComponent implements OnInit {
  @Input() foo : Foo;
  @Output() onChange : EventEmitter<Foo> = new EvenEmitter<Foo>();

  constructor() {
  }

  ngOnInit() {
  }
}

I nest that ChildComponent inside a ParentComponent.

<div id="parent">
  <app-child-component [foo]="parentFoo"></app-child-component>
</div>

Now even though I used 1-way binding here, since foo is an object and thereby passed by reference, any changes made to it in ChildComponent are also reflected in ParentComponent.

How can I prevent that? Is there a way to pass by value? Any best practices?


Solution

  • Alright, my best solution so far looks like this:

    export class ChildComponent implements OnInit {
      private _foo : Foo;
      @Input()
      set foo(value : Foo) { this._foo = Object.create(value || null); }
      get foo() : Foo { return this._foo; }
    
      @Output() onChange : EventEmitter<Foo> = new EventEmitter<Foo>();
    
      constructor() {
      }
    
      ngOnInit() {
      }
    }
    

    This does seem to work, however it's a lot of code for a single attribute. I still don't understand why there is no such functionality build into Angular (for example an @InputByValue decorator).

    I thought that when I want changes to be reflected back from child to parent, I would use two-way-binding [(foo)]="foo". Am I missing something here? Is there any reason not to do what I'm trying to do?