DEV Community

ILshat Khamitov
ILshat Khamitov

Posted on • Edited on

Auto binding Input() and Output() in Angular9+

Directives for auto binding Input() and Output() from host component to inner in Angular9+ application

Installation

npm i --save ngx-bind-io 
Enter fullscreen mode Exit fullscreen mode

Example

Without auto binding inputs and outputs

<component-name (start)="onStart()" [isLoading]="isLoading$ | async" [propA]="propA" [propB]="propB"> </component-name> 
Enter fullscreen mode Exit fullscreen mode

With auto binding inputs and outputs

<component-name [bindIO]> </component-name> 
Enter fullscreen mode Exit fullscreen mode

app.module.ts

import { NgxBindIOModule } from 'ngx-bind-io'; import { InnerComponent } from './inner.component'; import { HostComponent } from './host.component'; @NgModule({ ... imports: [ ... NgxBindIOModule.forRoot(), // in child modules import as "NgxBindIOModule" ... ] declarations: [ ... InnerComponent, HostComponent ... ], ... }) export class AppModule { } 
Enter fullscreen mode Exit fullscreen mode

inner.component.ts

import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; @Component({ selector: 'inner', changeDetection: ChangeDetectionStrategy.OnPush, template: ` <div *ngIf="isLoading">Loading... (5s)</div> <button (click)="onStart()">Start</button> <br /> {{ propA }} <br /> {{ propB }} ` }) export class InnerComponent { @Input() isLoading: boolean; @Input() propA = 'Prop A: not defined'; @Input() propB = 'Prop B: not defined'; @Output() start = new EventEmitter(); onStart() { this.start.next(true); } } 
Enter fullscreen mode Exit fullscreen mode

base-host.component.ts

import { BehaviorSubject } from 'rxjs'; export class BaseHostComponent { isLoading$ = new BehaviorSubject(false); onStart() { this.isLoading$.next(true); setTimeout(() => this.isLoading$.next(false), 5000); } } 
Enter fullscreen mode Exit fullscreen mode

host.component.ts

import { ChangeDetectionStrategy, Component } from '@angular/core'; import { BaseHostComponent } from './base-host.component'; @Component({ selector: 'host', changeDetection: ChangeDetectionStrategy.OnPush, template: ` <inner [bindIO]></inner> ` }) export class HostComponent extends BaseHostComponent { propA = 'Prop A: defined'; propB = 'Prop B: defined'; } 
Enter fullscreen mode Exit fullscreen mode

Debug

For global debug all bindings

import { NgxBindIOModule } from 'ngx-bind-io'; @NgModule({ ... imports: [ ... NgxBindIOModule.forRoot({debug: true}) ... ], ... }) export class AppModule { } 
Enter fullscreen mode Exit fullscreen mode

For debug on one place

<comp-name [bindIO]="{debug:true}"></comp-name> 
Enter fullscreen mode Exit fullscreen mode

Rules for detect inputs and outputs

Custom rules for detect output method

my-ngx-bind-outputs.service.ts

import { Injectable } from '@angular/core'; import { IBindIO, NgxBindOutputsService } from 'ngx-bind-io'; @Injectable() export class MyNgxBindOutputsService extends NgxBindOutputsService { checkKeyNameToOutputBind(directive: Partial<INgxBindIODirective>, hostKey: string, innerKey: string) { const outputs = directive.outputs; const keyWithFirstUpperLetter = innerKey.length > 0 ? innerKey.charAt(0).toUpperCase() + innerKey.substr(1) : innerKey; return ( (hostKey === `on${keyWithFirstUpperLetter}` && outputs.hostKeys.indexOf(`on${keyWithFirstUpperLetter}Click`) === -1 && outputs.hostKeys.indexOf(`on${keyWithFirstUpperLetter}ButtonClick`) === -1) || (hostKey === `on${keyWithFirstUpperLetter}Click` && outputs.hostKeys.indexOf(`on${keyWithFirstUpperLetter}ButtonClick`) === -1) || hostKey === `on${keyWithFirstUpperLetter}ButtonClick` ); } } 
Enter fullscreen mode Exit fullscreen mode

app.module.ts

import { NgxBindOutputsService, NgxBindIOModule } from 'ngx-bind-io'; import { MyNgxBindOutputsService } from './shared/utils/my-ngx-bind-outputs.service'; import { InnerComponent } from './inner.component'; import { HostComponent } from './host.component'; @NgModule({ declarations: [AppComponent], imports: [ ... NgxBindIOModule, ... ], declarations: [ AppComponent, InnerComponent, HostComponent, ... ], providers: [ ... { provide: NgxBindOutputsService, useClass: MyNgxBindOutputsService }, ... ], bootstrap: [AppComponent] }) export class AppModule { } 
Enter fullscreen mode Exit fullscreen mode

Links

Demo - Demo application with ngx-bind-io.

Stackblitz - Simply sample of usage on https://stackblitz.com

Top comments (0)