8

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?

2
  • You are probably looking for a pipe. You would have to decouple the ngModel into [ngModel]="data.name | trimPipe" (ngModel)="data.name=$event" Commented Sep 18, 2017 at 23:18
  • I see your point - I'll play with pipe after, but for now I think a directive should work...just can't figure out how Commented Sep 18, 2017 at 23:26

3 Answers 3

10

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'

Sign up to request clarification or add additional context in comments.

6 Comments

The change event triggers when leaving the field, but the value does not update (trimmed)
try changing it to ngModelChange event (or input event as mentioned at the bottom of my answer)
I got it to work with the following, but it seems a bit complex: (this.el.nativeElement as HTMLInputElement).value = (this.el.nativeElement as HTMLInputElement).value.trim();
As long as you are planning to reuse your directive on an input element this will work. What other cases would you expect a value to be trimmed?
I'm not sure - this was more theoritical (how to do) than practical. I'm now working on a pipe to do what I want as Ploppy suggested above.
|
2

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)

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.