7

I'm trying to have an input field format/mask values as they are typed, while having the actual model retain the raw (or differently formatted) value. I'm thinking phone numbers etc, but for simplicity am using uppercase for testing.

I've tried a bunch of stuff, hoping its as simple as a directive. But can't seem to get the display value to depart from the form value.

plunk: http://plnkr.co/edit/VH5zn4S8q28CBpFutBlx?p=preview

Here's the directive:

@Directive({
  selector: '[uppercase]',
  host: {
    '(input)': 'onInputChange()',
  }
})

export class UppercaseDirective {

  constructor(private model: NgFormControl) { }

  onInputChange() {
    let newValue = this.model.value.toUpperCase();
    this.model.viewToModelUpdate(newValue);
    this.model.valueAccessor.writeValue(newValue);
  }

}

and the form:

<form [ngFormModel]='myForm'>
  <input [ngFormControl]='myForm.controls.field' uppercase>
  <div>
    {{ myForm.value.field }}
  </div>
</form>
Steve
  • 1,326
  • 14
  • 21
  • why not Pipes? Sounds like you just want a different way of displaying the text. – Ed Morales Jun 08 '16 at 19:22
  • I want the formatting to happen in the input box - an input mask. I'm only displaying the value in the view for testing purposes. – Steve Jun 08 '16 at 19:28

2 Answers2

2

Try to update control reference directly like this:

onInputChange() {
  let newValue = this.model.value.toUpperCase();
  this.model.control.updateValue(newValue);
}

See also plunker http://plnkr.co/edit/XYPWYgA8lbg2EdxPqzWj?p=preview

yurzui
  • 205,937
  • 32
  • 433
  • 399
  • Makes sense. Thanks. I was trying to have the model value and display value different, but your answer gave me the answer: http://plnkr.co/edit/VH5zn4S8q28CBpFutBlx?p=preview – Steve Jun 08 '16 at 22:32
1

To be honest, i am still learning angular2 and the tech is still really immature to say this is the best way of doing it but after playing around with it:

import {Directive, ElementRef, Output, EventEmitter} from '@angular/core';
import {NgFormControl} from '@angular/common';

@Directive({
  selector: '[uppercase]',
  host: {
    '(input)': 'onInputChange()',
  }
})

export class UppercaseDirective {

  @Output() onChange = new EventEmitter();
  rawValue: string = '';

  constructor(private model: NgFormControl, private elementRef: ElementRef) { }

  onInputChange() {
    let str = this.model.value;
    this.rawValue = this.rawValue.substring(0, str.length) + str.substring(this.rawValue.length, str.length);
    let newValue = this.rawValue.toUpperCase();
    this.model.viewToModelUpdate(newValue);
    this.model.valueAccessor.writeValue(newValue);
    this.onChange.emit(this.rawValue);
  }

}

then you can get it like this:

<input [ngFormControl]='myForm.controls.field' uppercase (onChange)="raw = $event">
<div>
   {{ raw }}
</div>

Since whenever you update the model, the variable will change. You have to do is separate. Tried it in your plnkr and it worked.

EDIT: Might need some work for different scenarios though haha

Ed Morales
  • 1,027
  • 5
  • 9