简体   繁体   中英

Referencing a model in Angular with `(ngModelChange)`?

Simplification : I have a calculator which won't allow "7" to be the result ( valid will be false ).

在此处输入图片说明

The calculator itself is component which implements ControlValueAccessor .

The model is

interface IModel {
  a, b, c: number | null; 
}

( a is the left digit , b is the middle one , and c is the result)

This is how I wrote the template :

 <input type='text' [ngModel]='myModel.a'   (ngModelChange)='calc("a",$event)'/> + 
 <input type='text' [ngModel]='myModel.b'   (ngModelChange)='calc("b",$event)'/> = 
 <input type='text' readonly [ngModel]='myModel.c'   />

I didn't use banana in a box becuase I had to do a logic on each modification of the inputs.
I didn't use getter/setter either becuase otherwise- in the setter - I'd would have problem with controlling updates.

So that's why I use (ngModelChange) . Where on each change I call the calc function :

 calc(propName,e) {
    this.myModel[propName] = e;
    this.myModel.c = +this.myModel.a + +this.myModel.b;
    this.onChangeCallback(this.myModel);
  }

But now things get complicated.

When changing the first input , I must tell the calc function :

  • To update the model for the control who activated the change - that's why I send "a" in calc("a",$event) and "b" in calc("b",$event) .
  • Run calculation against the updated model.

But this correlation seems WRONG to me :

在此处输入图片说明

Sure - I could add template variable to each and send that variable and to read .value in the calc function.

But I think I'm going into the non-angular way

Question

How can I reference the model of the control when updating the input? ( Along with doing custom logic when set)

ONLINE DEMO

PS - I don't have the (input) event since i'm using Angular in Nativescript.

You can use banana in a box and your custom logic together.

Check this stackblitz

You can use [(ngModel)] and (ngModelChange)="calc($event)" together. What this will do is to update your model first and then call your custom function.

So, change your markup as follows

<input type='text' [(ngModel)]='myModel.a'   (ngModelChange)='calc()'/> + 
<input type='text' [(ngModel)]='myModel.b'   (ngModelChange)='calc()'/> = 
<input type='text' readonly [ngModel]='myModel.c'/>

calc method:

calc() {
   this.myModel.c = this.myModel.a * 1 + this.myModel.b * 1
}

Note: * 1 is for parsing string to number. It's a hack I'd like to use.

You can use Reactive from like this , Not much in template file ie html , all dirty stuff handle by Typescript

<form class="form-horizontal"  [formGroup]="calculationForm" novalidate >
     <input type='text' "formControlName"='a'  /> + 
     <input type='text' "formControlName"='b'/> = 
     <input type='text' "formControlName"='c'   />
</form>

Ts file would be

      createForm() {
        this.calculationForm= this.fb.group({
          a: '',
          b: '',
          c: ''
        });
      }

  get a() {
    return this.calculationForm.get('a');
  }

  get b() {
    return this.calculationForm.get('b');
  }

  get c() {
    return this.calculationForm.get('c');
  }

    private onChanges(): void {
        this.a.valueChanges.subscribe(() => this.calculate());
        this.b.valueChanges.subscribe(() => this.calculate());
    }

  private calculate() {
        if (this.a.value && this.b.value) {
         this.c.setValue(this.a.value + this.b.value , {emitEvent: false});
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM