2

I am trying to implement two way data binding in angular components. Currently its in a parent child mode.

parent.component.html

<child [(title)]="title"></child>
<span style="color: red">This is parent component {{title}}</span>

parent.component.ts

title = 'app';

child.component.html

<span style="color: blue">This is child component {{title}}</span>

child.component.ts

@Input() title: any;
  @Output() pushTitle = new EventEmitter();

  constructor() { }

  ngOnInit() {
    this.title = 'new title';
    this.pushTitle.emit(this.title);
  }

The title should implement on the parent component as well, when I change it from the child. Also, I am not sure why the parent code keeps going in a loop for no reason. I have added text in html just to test if its updated in both the components, but its updating only in the child, and not in the parent. I am coming from the angularjs background, and two way data binding worked seamlessly in it. I am just confused what I am doing wrong(I know its a noob question).

Demo here: https://stackblitz.com/edit/angular-xttmxg

1
  • Simple way is update from @Output() pushTitle = new EventEmitter(); to @Output() titleChange = new EventEmitter(); Commented Oct 23, 2020 at 13:20

3 Answers 3

2

There is another way that you can achive the same.

@Input() title: any;
@Output() titleChange: EventEmitter<any> = new EventEmitter<any>();

changeValue() {
  this.title= !title;
  this.titleChange.emit(this.title);
}

Have a look at Angular documentation about two way binding

Sign up to request clarification or add additional context in comments.

6 Comments

This makes no sense. You will get an error title is not defined.
let me create a stackblitz :)
@ritaj please have a look at stackblitz.com/edit/angular-two-way
Please re-read your answer given. It uses undefined variable. Other than that, yes, that definitely works. Nice work!
@RukshanDangalla, the stackblitz code is fantastic! I just have one question, can't I just use [(fontSizePx)]="fontSizePx", and assign the input variable as fontSizePx? instead of using size?
|
1

Two way data binding only works for template - component interaction.

If you want to send title change to parent component, you should do something like this:

Parent template and component:

<child [title]="title" (pushTitle)="onTitleChange(value)"></child>
<span style="color: red">This is parent component {{title}}</span>

onTitleChange(value) {
    this.title = value;
}

Followup question:

Template:

 <input [(ngModel)]="inputModel">

Component:

inputModel: string;

Now, every time you type something into input field you will see changes in component model, OR when change inputModel value programmatically, you will see the change in HTML input.

3 Comments

Thanks. In what scenario will I be able to use [(title)] then?
Edited the answer.
if @ritaj answer satisfies you, you should mark his answer as correct. Thank you.
1

You are somehow creating an infinite update cycle using the 2-way-binding. This leads to the infinite loop and eventual stack overflow you noticed.


To fix this, preferably, you want to add some logic to the titleChange event (this is the banana-part of the banana-in-a-box syntax, i.e. the part in parens in [(title)] which is getting automatically translated into an event emitter named titleChange). For example, you might want to skip updating the title property of the parent component if its equal to the update emitted by the child component.

This means you should split up [(title)] into (titleChange)="titleChange($event)" and [title]="title". The first part lets you pass the updated title as $event and then process it in a function titleChanged (name is arbitrary in this case). The second part has the effect that the child component receives updates of the parent component's title property.

Another common pattern is to make title private (commonly with a prefixed underscore, e.g. _title) and then add a getter get title() { return this._title;} so that you can (1) encapsulate this property and (2) add some processing. In your case this is not needed, but it doesn't hurt either. ;-)


Here's a plunkr containing these changes.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.