TSG
TSG

Reputation: 4617

Angular 4 directive to manipulate input text

I have created a simple directive to trim my input text (I plan to expand it's functionality later - so please don't recommend a simple onkeyup function), I would like to make a directive work.

I use my directive like this:

    <input type="text" class="form-control" inputTextFilter [(ngModel)]="data.name">

and my directive is as follows:

import { Directive, HostBinding, HostListener } from '@angular/core';

@Directive({
  selector: '[inputTextFilter]'
})

export class InputTextFilterDirective {
  value: string;

  constructor() {
    console.log('contrusted InputTextFilterDirective');
    this.value = '';
  }

  @HostListener('change')
  onChange($event) {
    console.log('in change InputTextFilterDirective');
    this.value = $event.target.value.trim();
    console.log(this.value);
  }
}

I see the constructor message log to the window, but the on change message never appears, and my value never changes (spaces aren't trimmed from end). I suspect hostListeners and hostProperties aren't right as I've seen lots of conflicting examples...but can't confirm a right way.

What's wrong with this?

Upvotes: 8

Views: 21014

Answers (3)

amal
amal

Reputation: 3170

Change your directive to

import { Directive, HostBinding, HostListener, ElementRef } from '@angular/core';

@Directive({
  selector: '[inputTextFilter]'
})

export class InputTextFilterDirective {
  @Input() ngModel: string;

  constructor(private el: ElementRef) {
    console.log('constructed InputTextFilterDirective');
    (el.nativeElement as HTMLInputElement).value = '';
  }

  @HostListener('change')
  onChange() {
    console.log('in change InputTextFilterDirective');
    (this.el.nativeElement as HTMLInputElement).value.trim();
    console.log(this.ngModel);
  }
}

Try and see if that works. If it didn't, try changing the event from 'change' to 'input' or 'ngModelChange'

Upvotes: 10

Mahmoud
Mahmoud

Reputation: 571

Here you go:

import { Directive, ElementRef, HostListener } from '@angular/core';

@Directive({
    selector: '[trim-text]'
})
export class TrimTextDirective {
    constructor(
        private el: ElementRef,
    ) {}

    @HostListener('blur')
    // @HostListener('input')
    @HostListener('change')
    applyTrim() {
        let ele = this.el.nativeElement as HTMLInputElement;
        if (typeof ele.value === 'string') {
            ele.value = ele.value.trim();
        }
    }
}

If you uncomment "@HostListener('input')" you wont be able to write spaces (in case you want to trim the sides and allow having spaces in between)

Upvotes: 2

KingMario
KingMario

Reputation: 171

You may try this directive created by me: https://www.npmjs.com/package/ngx-trim-directive

It lies on a very simple fact that Angular listens to input event to bring the view-to-model binding into being.

Upvotes: 0

Related Questions