Search code examples
htmlangularangular-reactive-formsangular2-custom-component

How to handle input events on custom input component in Angular?


I'm trying to create a custom Input component using Reative Form in Angular 7 but i'm having trouble passing events to the input field.

My component has a label and an input field and a specific layout. My component html looks like this:

<div id="customInputGroup"  [formGroup]="parentFormGroup" [ngClass]="{'input-value': hasValue()}">
    <label [for]="inputId">{{label}}</label>
    <input [id]="inputId"  [name]="inputName"  class="form-control" [placeholder]="placeholder" [formControlName]="inputName" [mask]="mask">
</div>

And in my Component:

@Component({
  selector: 'app-input-field',
  templateUrl: './input-field.component.html',
  styleUrls: ['./input-field.component.css']
})
export class InputFieldComponent implements OnInit {


  @Input('placeholder') placeholder = '' ;
  @Input('label') label = '';
  @Input('inputId') inputId = '';
  @Input('inputName') inputName = '';
  @Input('parentFormGroup') parentFormGroup:FormGroup;
  @Input('mask') mask;
  constructor() { }

  ngOnInit() {
  }

  hasValue(){
    return (this.parentFormGroup.get(this.inputName).value != undefined 
    && this.parentFormGroup.get(this.inputName).value != null 
    && this.parentFormGroup.get(this.inputName).value != '')
  }

Everything was working fine till i had to handle an input onBlur event(or it could be any other input event). The result i want is to call my component passing any event like this:

<app-input-field (blur)="functionName()"></app-input-field>

or

<app-input-field (keyup)="functionName()"></app-input-field>

And my component will be able to pass these events to my input field 'dynamically'. Is it possible to do it?


Solution

  • for blur event you need to create a eventemitter with the same name and emit this event on input elemnt blur emit

    export class InputFieldComponent implements OnInit {
    
      @Output() blur:EventEmitter<any> = new EventEmitter(); // 👈
    
      constructor() { }
    
      ngOnInit() {
      }
    
    }
    

    template

    <input type="text" (blur)="blur.emit($event)"  >
    

    app.template

    <app-input-field (blur)="onBlur($event)" (keyup)="onKeyup($event)"></app-input-field>
    

    we did this for the blur event because the event is not bubble where the keyup will work without create any custom event because it bubble.

    demo 🔥🔥

    you can implement two way data binding like this

      @Input() value:EventEmitter<any> = new EventEmitter();
    
      @Output() valueChange:EventEmitter<any> = new EventEmitter();
    

    template

    <app-input-field  [(value)]="name" ></app-input-field>
    

    demo 🌟🌟

    any bubble event like input,keypress,keyup,keydown you can capture on the element itself or you can work around it like what we did on blur event.