I'm pretty new to Angular and I'm trying to build some re-usable components, like a input text component for example. I want to customise it with all sorts of built-in methods, validations, associated labels and error labels, etc.
I've mostly managed to to it. What I'm trying now to achieve is to re-render the parent component (and all children implicitly) when a property is changed.
I'm getting the callback triggered in the parent and assigning the value to my text property, but the DOM does not update with the new value.
Parent Component
import { Component, Input } from '@angular/core';
@Component({
selector: 'parent',
template: '<input-text [text]="text" [onChange]="onChange"></input-text> <p>The text is now {{text}}</p>'
})
export class ParentComponent {
text: string;
onChange($text) {
this.text = $text;
console.log('onChange', this.text); // <-- it gets here on child input
}
}
Input Text - Child Component
import { Component, Input } from '@angular/core';
@Component({
selector: 'input-text',
template: '<input type="text" [(ngModel)]="text" (ngModelChange)="onChange($event)" [value]="text"/>',
})
export class InputTextComponent {
@Input() text: string;
@Input() onChange: Function;
}
So this is it. Writing in the child component triggers the parent's onChange
function, I update the text
property but the template message does not change.
I'm basically trying to create an uncontrolled component, simliar to React. Also, if I add more input-text
children they don't share the same text, although the parent's text
property is a single one and theoretically is passed to all children.
What I've tried
I've also tried using ngOnChanges
in the child component as mentioned here and to use the changeDetection
property as mentioned here but neither worked. The problem appears to be in the parent
I also tried using @Input()
in the parent component instead for the text property.
I'm pretty sure I'm missing something simple but can't figure out what.
When text
changes I want to see that in the DOM, and if I use 10 input-text
components that get passed the same text
property I would expect all of them display that.
Ok, it was simple like I expected. I was looking over this answer as a workaround and noticed that in the parent onChange
function it didn't recognise this.chRef
or other properties.
So I immediately realised I wasn't properly binding my function. So I changed the parent template to contain
[onChange]="onChange.bind(this)"
and it now works properly.
Nevertheless, if you have suggestions as to how this code could be improved please let me know.