6

I have a directive on an html input box that holds numeric values. When a user pastes a number into the textbox I have a directive that "cleans" the number (strips commas, dollar signs, etc). The cleaning code seems to work fine however my model is not being updated with the cleaned value even though the text box is showing my cleaned value.

How do I get my model updated with the new value?

Plnkr here

Here is a stripped down example:

app.ts

@Component({
  selector : 'my-app',
  template : `
  <div>
    <br/>
    <br/>
    <p>Stack Overflow person - give focus to text box and then lose focus by clicking elsewhere in the screen. <br/>The model is not updated.</p>
    <br/>Model value: {{ balanceAmount }}
    <br/>
    <br/>
    <input type="text" [(ngModel)]="balanceAmount" myCurrencyFormatter  /><br/>
  </div>
  `,
})
export class App {
  name:string;
  constructor(private mycurpipe: MyCurrencyPipe) {
    this.balanceAmount = 1234567.89;
  }
}

Currency-Formatter-Directive.ts

@Directive({ selector: "[myCurrencyFormatter]" })
export class MyCurrencyFormatterDirective implements OnInit {

  private el: any;

  constructor(
    private elementRef: ElementRef,
    private currencyPipe: MyCurrencyPipe
  ) {
    this.el = this.elementRef.nativeElement;

  }

  ngOnInit() {
    this.el.value = this.currencyPipe.transform(this.el.value);
  }

  @HostListener("focus", ["$event.target.value"])
  onFocus(value) {
    this.el.value = this.currencyPipe.parse(value); // opossite of transform
  }

  @HostListener("blur", ["$event.target.value"])
  onBlur(value) {
    this.el.value = this.cleanNumber(value); //"987654" ;//this.currencyPipe.transform(value);
  }
  
  cleanNumber (value: number) {
    return 8888888; // clean logic goes here, removed for plunk example
  }
  

}

Plnkr here

2
  • Can you update a model in the component? Commented Mar 2, 2017 at 21:14
  • Yes - for example, in my real life application, <input (blur)="calculateTotal" ...> works where I take the value of the model and perform some calculations and update the the model "TotalValue." Commented Mar 2, 2017 at 21:17

1 Answer 1

10

You need to add Emitter for your model. This is the way to implement 2 way binding in Angular 2. Take a look at line @Output() ngModelChange = new EventEmitter(); and how I used this variable to emit the change to caller.

import { Directive, HostListener, ElementRef, OnInit, EventEmitter, Output } from "@angular/core";
import { MyCurrencyPipe } from "./my-currency.pipe";

@Directive({ selector: "[myCurrencyFormatter]" })
export class MyCurrencyFormatterDirective implements OnInit {

  private el: any;
  @Output() ngModelChange = new EventEmitter();

  constructor(
    private elementRef: ElementRef,
    private currencyPipe: MyCurrencyPipe
  ) {
    this.el = this.elementRef.nativeElement;

  }

  ngOnInit() {
    this.el.value = this.currencyPipe.transform(this.el.value);
  }

  @HostListener("focus", ["$event.target.value"])
  onFocus(value) {
    this.el.value = this.currencyPipe.parse(value); // oposite of transform
    this.ngModelChange.emit(this.el.value);
  }

  @HostListener("blur", ["$event.target.value"])
  onBlur(value) {
    this.el.value = this.cleanNumber(value); //"987654" ;//this.currencyPipe.transform(value);
    this.ngModelChange.emit(this.el.value);
  }
  
  cleanNumber (value: number) {
    return 8888888;
  }

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

3 Comments

Thank you. To add, the eventEmitter MUST BE called ngModelChange. If it is anything else then you must specifically add a listener to the element that is using the attribute directive. e.g. <input ...(someEvent)="balanceAmount =$event">
Does this work using ReactiveForms? I added an Output EventEmitter similar to your example and then invoked this.ngModelChange.emit(value), but it doesn't seem to work so I'm assuming this is for Template Driven Forms only? I've posted a question here if you're interested: stackoverflow.com/q/43380390/1148107 that contains a plunker
I must be missing something simple with @Output. this is clearing my field when the method is called. Did you have to update the html as well?

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.