Search code examples
angularangular-materialangular-directive

I need to create a Angular directive to clear content entered in input field in icon button click


I have created a directive which will show clear button icon only if there is any content inside input field. Also I need that on button click input content should get cleared.

As host element is not input itself value is setting to empty inside directive but not getting reflected in the component.

HTML

<mat-form-field>
    <input matInput  #inputVal type="text" placeholder="Clearable input" [(ngModel)]="value" />
    <mat-icon [clearInput]= "inputVal.value" class="suffix" matSuffix >Close</mat-icon>
</mat-form-field>

Directive

@Directive({
  selector: '[clearInput]',
  exportAs: 'clearInput'
})
export class clearInputDirective implements OnChanges{
   
    @Input('clearInput') inputValue: any;
    constructor(private el: ElementRef, private renderer:Renderer2) {
      
  }
  @HostListener('click') onClick() {
    this.inputValue = null;
  }

  ngOnChanges(changes: SimpleChanges){
    if(changes.inputValue){
   
     if(this.inputValue){
        this.renderer.setStyle(this.el.nativeElement, 'display', 'block');
       }
       else {
        this.renderer.setStyle(this.el.nativeElement, 'display', 'none');
       }
    }
  }
}

Solution

  • This problem acc. to me is clearInput is not bind to your inputVal it's just taking a value and acting accordingly in directive. for your approach to work you need full reference of inputVal in directive.

    Right now it's just a primitive value that's why when you change the value to null it's only on directive level.

    [EDIT]

    Try below code. - as you are using ngmodel then we need reference of ngmodel

    <div class="input">
     <input matInput  clearInput [clearInput]= "value" #inputVal type="text" placeholder="Clearable input" [(ngModel)]="value" />
    <div class="alwaysCloseButtonWillBethere" 
        matSuffix >Close</div>
    </div>
    

    clear directive -- just i have taken a constant like html is like div[input , close] when you click on close input will get empty

        import { Directive, OnChanges, Input, HostListener, ElementRef, Renderer2, SimpleChanges, OnInit, OnDestroy} from '@angular/core';
    import { NgModel } from '@angular/forms';
    
    @Directive({
      selector: '[clearInput]',
      exportAs: 'clearInput'
    })
    export class ClaerinputDirective implements OnChanges , OnInit , OnDestroy{
       
        @Input('clearInput') inputValue: any;
        constructor(private el: ElementRef, private renderer:Renderer2 , private model: NgModel) {
          
      }
    
      ngOnInit(){
         this.el.nativeElement.parentNode.children[1].addEventListener('click', () =>{
           this.model.control.reset();
         })
      }
    
      ngOnChanges(changes: SimpleChanges){
       if(changes.inputValue){
          if(this.inputValue){
           this.renderer.setStyle(this.el.nativeElement.parentNode.children[1], 'display', 'block');
           }
           else {
            this.renderer.setStyle(this.el.nativeElement.parentNode.children[1], 'display', 'none');
           }
       }
      }
    
      ngOnDestroy() {
         this.el.nativeElement.parentNode.children[1].removeEventListener('click',null
         );
      }
    }
    

    if dom node are not static , then use below it based on class name i have taken class name --- alwaysCloseButtonWillBethere

         import { Directive, OnChanges, Input, HostListener, ElementRef, Renderer2, SimpleChanges, OnInit, OnDestroy} from '@angular/core';
    import { NgModel } from '@angular/forms';
    
    @Directive({
      selector: '[clearInput]',
      exportAs: 'clearInput'
    })
    export class ClaerinputDirective implements OnChanges , OnInit , OnDestroy{
       
        @Input('clearInput') inputValue: any;
        nodeToHideAndShow: HTMLElement;
        constructor(private el: ElementRef, private renderer:Renderer2 , private model: NgModel) {
          
      }
    
      getNode(){
       if(!this.nodeToHideAndShow){
         this.nodeToHideAndShow = this.el.nativeElement.parentNode.querySelector('.alwaysCloseButtonWillBethere');
        }
    
      }
      ngOnInit(){
        this.getNode();
        if(!this.nodeToHideAndShow){
          // alert('Add a class  alwaysCloseButtonWillBethere')
        } else {
          console.log('d');
          this.nodeToHideAndShow.addEventListener('click', () => {
           this.model.control.reset();
         })
        }
         
      }
    
      ngOnChanges(changes: SimpleChanges){
       if(changes.inputValue){
         this.getNode();
          if(this.inputValue){
           this.renderer.setStyle( this.nodeToHideAndShow, 'display', 'block');
           }
           else {
            this.renderer.setStyle( this.nodeToHideAndShow, 'display', 'none');
           }
       }
      }
    
      ngOnDestroy() {
        if( this.nodeToHideAndShow){
              this.nodeToHideAndShow.removeEventListener('click',null);
          }
      }
    }