Angular 4 directive to manipulate input text
Asked Answered
F

3

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?

Frydman answered 18/9, 2017 at 23:12 Comment(2)
You are probably looking for a pipe. You would have to decouple the ngModel into [ngModel]="data.name | trimPipe" (ngModel)="data.name=$event"Affright
I see your point - I'll play with pipe after, but for now I think a directive should work...just can't figure out howFrydman
V
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'

Valenciavalenciennes answered 18/9, 2017 at 23:32 Comment(6)
The change event triggers when leaving the field, but the value does not update (trimmed)Frydman
try changing it to ngModelChange event (or input event as mentioned at the bottom of my answer)Valenciavalenciennes
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();Frydman
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?Valenciavalenciennes
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.Frydman
@HostListener('input') onChange() { ... } did the trick, I am finally able to remove Spacing diaeresis - umlaut ¨ from the input. It is somehow impossible to block it from user input. By typing ¨ it allows user to enter any other symbol such as & (, etc. It is quite weird.Ode
T
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)

Theme answered 13/10, 2020 at 23:28 Comment(0)
J
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.

Johathan answered 16/10, 2018 at 3:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.