IvanS95
IvanS95

Reputation: 5742

How to correctly build a directive that trims an input's value?

I'm trying to build a simple directive that trims the value of an input field when the blur event is fired.

The idea is that I want to make sure that any trailing and leading white spaces are removed, so that data saved is correct. I know I could simply use trim() when I save the value prior to sending it on a request; but I'm trying to do it in a directive since I already have a large application with lots of inputs, so it seems easier to just build a directive that I can apply to the inputs.

So far I have this code:

TrimDirective

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

@Directive({
  selector: '[appTrim]'
})
export class TrimDirective {

  constructor(private el: ElementRef) { }

  @HostListener('blur') onBlur() {
    this.el.nativeElement.value.trim();
  }

}

Input Element

 <div class="wsm-card-header d-flex justify-content-end">
      <input appTrim type="text" class="wsm-input">
 </div>

However it seems the directive isn't working as it should; if I click outside the input to remove focus, the value in it still has any space I typed in.

I haven't worked much with directives so I'm not sure if there are some caveats, usually any input I have is part of a ReactiveForm o just a FormControl by itself so I can subscribe to valueChanges and the like; but I wanted to know if a directive can do what I'm looking for and if I'm doing something wrong.

Upvotes: 2

Views: 2603

Answers (2)

IvanS95
IvanS95

Reputation: 5742

After working a bit more, I noticed simply setting the value of this.el.nativeElement.value to be equal to its trimmed value didn't work that well while using FormControl, so even if the whitespaces were removed on Blur, the form control's value still had them and could be sent on the request.

So at the end I was able to make it work with ReactiveForms by injecting NgControl in my directive's constructor and using NgControl.control.setValue() to pass the trimmed value, which is great since it triggers the valueChanges observable of the FormControl and updates its value on blur.

Directive code ends up looking like this:

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

@Directive({
  selector: '[appTrim]'
})
export class TrimDirective {

  constructor(private el: ElementRef,  @Optional() private ngControl: NgControl) { }

  @HostListener('blur') onBlur() {
    this.ngControl.control.setValue(this.el.nativeElement.value.trim());
  }

}

Upvotes: 3

Aakash Garg
Aakash Garg

Reputation: 10979

Changes inside directive

@HostListener('blur') onBlur() {
    this.el.nativeElement.value = this.el.nativeElement.value.trim();
  }

Upvotes: 1

Related Questions