Directives for auto binding Input() and Output() from host component to inner in Angular9+ application
Installation
npm i --save ngx-bind-io
Example
Without auto binding inputs and outputs
<component-name (start)="onStart()" [isLoading]="isLoading$ | async" [propA]="propA" [propB]="propB"> </component-name>
With auto binding inputs and outputs
<component-name [bindIO]> </component-name>
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 { }
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); } }
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); } }
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'; }
Debug
For global debug all bindings
import { NgxBindIOModule } from 'ngx-bind-io'; @NgModule({ ... imports: [ ... NgxBindIOModule.forRoot({debug: true}) ... ], ... }) export class AppModule { }
For debug on one place
<comp-name [bindIO]="{debug:true}"></comp-name>
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` ); } }
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 { }
Links
Demo - Demo application with ngx-bind-io.
Stackblitz - Simply sample of usage on https://stackblitz.com
Top comments (0)