Search code examples
angularonchange

How to trigger ngOnChanges


How to trigger ngOnChanges on a form in a component?

I want to calculate a new total price (gesamtpreis) whenever any form input changes.

I looked at other answers, but this just made my code more weird instead of working. Do I need the @Input and is it correctly wired.

component HTML:

<div class="card my-5">
<div class="card-body">

<form #carConfigurationForm="ngForm" ng-change="ngOnChanges">
  <div class="form-group">
    <label for="extra">Extra 1&nbsp;</label>
    <select name="extra1" class="btn btn-secondary dropdown-toggle">
      <option value="default">Kein Extra</option>
      <option *ngFor="let extra of selectExtra" [value]="extra.name">{{extra.name}} {{extra.preis}}&euro;</option>
    </select>
  </div>
  <div class="form-group">
    <label for="gesamtpreis">Gesamt&nbsp;</label>
    <span name="gesamtpreis" [innerHTML]="gesamtpreis"></span>
  </div>
</form>

component code:

import { Component, OnInit, OnChanges, Input } from '@angular/core';
import { Extra } from '../model/extra';
import { ExtraService} from '../service/extra.service';
import { SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-car-configuration-form',
  templateUrl: './car-configuration-form.component.html',
  styleUrls: ['./car-configuration-form.component.sass']
})
export class CarConfigurationFormComponent implements OnInit, OnChanges {

  selectExtra : Extra[] = [];

  gesamtpreis : string = 'kein Preis';

  constructor(private extraService: ExtraService) { }

  getSelectedExtra(): void{
    this.extraService.findAll()
      .subscribe(selectExtra => this.selectExtra= selectExtra);
  }

  ngOnInit() {
    this.getSelectedExtra();

  }

  @Input() extra1: string = '';

  ngOnChanges(changes: SimpleChanges) {
    // changes.prop contains the old and the new value...
    console.log('zzz ngOnChanges');
    this.gesamtpreis = "zzz"; //changes.toString();
  }
}

Solution

  • ngModel

    Why do you want to use ngOnChanges exactly?

    You can just use ngModel to bind to values in a template form:

    <select name="extra1" class="btn btn-secondary dropdown-toggle" [ngModel]="gesamtpreis">
    

    If you want other logic to trigger when the value changes you can just make getters and setters for that value:

    private _gesamtpreis = 'kein Preis';
    
    get gesamtpreis() {
      return this._gesamtpreis
    }
    
    set gesamtpreis(value) {
      this._gesamtpreis = value
      /* Some other logic goes here... */
      /* You could event push to a subject here, whatever floats your boat... */
    }
    

    Binding to the (change) event

    <form #carConfigurationForm="ngForm" (change)="formChanged(carConfigurationForm)">
    

    Script:

    formChanged(event) {
        console.log(event.value)
    }
    

    In your case you don't even need to pass the form reference into the function. Since it seems you only want to get some notice of the form being changed.

    Here's a Stackblitz for you to play with.