A New Way to Set Inputs on Angular ComponentRefs
When creating dynamic components in angular applications or writing tests, we use the component reference instance property to change input values.
For example:
@Directive({
selector: '[container]',
})
export class ContainerDirective {
constructor(private vcr: ViewContainerRef) {}
ngOnInit() {
const ref = this.vcr.createComponent(FooComponent);
ref.instance.text = 'bar';
}
}
This approach will work, but it consists few drawbacks:
- Setting input properties manually wouldn’t trigger the
NgOnChangeslifecycle hook - It’s challenging to test
OnPushcomponents since they are not marked for check - As a result of input
aliasing, setting input properties was fragile because a property name on a component may differ from the actual input name - It doesn’t throw an error if the input doesn’t exist
Since v14.1.0, Angular added the setInput() method to the component reference, making the above issues a thing of the past:
@Directive({
selector: '[container]',
})
export class ContainerDirective {
constructor(private vcr: ViewContainerRef) {}
ngOnInit() {
const ref = this.vcr.createComponent(FooComponent);
ref.setInput('text', 'Angular');
ref.setInput('myAlias', 'v14.1.0');
// This will throw an error
ref.setInput('doesNotExist', 'error');
}
}
These modifications unify inputs across dynamically created components and the ones referenced in templates.
There is only one drawback to this approach over using the instance directly — it isn’t typed. You can type-safe it like this if you don’t use an alias:
const textInput: keyof FooComponent = 'text';
this.vcr.createComponent(FooComponent).setInput(textInput, 'bar');
Reference
https://medium.com/netanelbasal/a-new-way-to-set-inputs-on-angular-componentrefs-6214f95db63d