Home > Software design >  Angular 10, fire function when component property changes
Angular 10, fire function when component property changes

Time:10-15

I have a question regarding nchange detection within Angular. In my class I have a property called "showInvoiceDetails = false;" later on when the user clicks a button this will be set to "true" and I would expect angular's OnChanges lifecycle hook to run. however this seems te be not the case and I wonder why.

My component code:

import { IAgreementListItem, ICase } from '@abf/lease-factory-gateway-clients';
import { Component, HostListener, Input, OnChanges, OnInit, ChangeDetectorRef  } from '@angular/core';

import { FormControl, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'abf-lease-contract-form-invoice-details',
  templateUrl: './lease-contract-form-invoice-details.component.html',
  styleUrls: ['./lease-contract-form-invoice-details.component.scss']
})

export class LeaseContractFormInvoiceDetailsComponent implements OnInit, OnChanges {

  constructor(private cd: ChangeDetectorRef ) {}

  @Input() requestForDrawdownObject: ICase = {} as ICase;

    loading: boolean = true;
    error: string = "";
    serviceAgreements: IAgreementListItem[] | any;

  showInvoiceDetails =  false;
  showSupplierDetails = false;

  // Form variables
  invoiceDetailsForm = new FormGroup({
    invoiceNumber: new FormControl("", [Validators.required, Validators.pattern('[A-Za-z0-9 _-] ')]),
    invoiceDate: new FormControl("", [Validators.required]),
    invoiceTotalValue: new FormControl("", [Validators.required, Validators.pattern('[0-9.,] ') ]),
    vatPercentage: new FormControl("", [Validators.required]),
    invoiceVatValue: new FormControl(""),
    invoiceTotalValueExclVat: new FormControl(""),
    address: new FormControl('')
  });




  @HostListener('keyup', ['$event'])
  onKeyUp(event: any) {    
    // Logs the id of the element 
    // where the event is originally invoked. 
    if (event.keyCode === 13) {

      switch (event.target.id) {
        case 'vatTarifOne':
          console.log('execute tarif one logic');
          break;
        case 'vatTarifTwo':
          console.log('execute tarif two logic');
          break;
        case 'vatTarifThree':
          console.log('execute tarif three logic');
          break;
        case "invoiceDetailsCancelChanges":
          this.cancelInvoiceDetailsHandler();
          break;
        case "invoiceDetailsSaveChanges":
          this.saveInvoiceDetailsHandler();
          break;
        default:
          break;
      }
    }
  }

  changeInvoiceDetailsHandler() {
    this.showInvoiceDetails = true;
  }


  saveInvoiceDetailsHandler() {
    this.showInvoiceDetails = false;
    this.cd.detectChanges();
    // this.showInvoiceDetails = false;
  }

  cancelInvoiceDetailsHandler() {
    this.showInvoiceDetails = false;
  }


  updateAddress(event) {
    if (event !== "undefined") {
      this.invoiceDetailsForm.patchValue({ 
        address: event?.target?.value?.toString()
      });
    }
  }

  reformatTotalValue(newInvoiceTotal) {
   
    this.invoiceDetailsForm.patchValue({
      invoiceTotalValue: newInvoiceTotal?.target?.value.toString()
    });
  }

  ngOnChanges(changes):void {
    console.log('change trigger', changes)
  }


  ngOnInit(): void {
    console.log('---------', this.requestForDrawdownObject);

      this.invoiceDetailsForm.patchValue({
        invoiceNumber: 1223131122,
        invoiceDate: this.requestForDrawdownObject?.requestForDrawdown?.invoices[0]?.invoiceDate,
        invoiceTotalValue: this.requestForDrawdownObject?.requestForDrawdown?.invoices[0]?.amountIncludingVAT,
        vatPercentage: this.requestForDrawdownObject?.requestForDrawdown?.invoices[0]?.percentageVAT,
        invoiceVatValue: this.requestForDrawdownObject?.requestForDrawdown?.invoices[0]?.amountVAT,
        invoiceTotalValueExclVat: this.requestForDrawdownObject?.requestForDrawdown?.invoices[0]?.amountExcludingVAT
    });

      console.log('invoice form details', this.invoiceDetailsForm)
  }

  
}

My html:

<div >
                    
    <h3>Factuurgegevens</h3>
    <div  *ngIf="!showInvoiceDetails">
        <div >
            <p >Factuurgegevens</p>
            <p >{{invoiceDetailsForm.get('invoiceNumber').value }}</p>
        </div>

        <div >
            <p >Factuurdatum</p>
            <p  >{{ invoiceDetailsForm.get('invoiceDate').value }}</p>
        </div>

        <div >
            <p >Totale factuurwaarde</p>
            <p  ><abf-display-currency [value]="invoiceDetailsForm.get('invoiceTotalValue').value"></abf-display-currency></p>
        </div>

        <div >
            <p >BTW percentage</p>
            <p >{{ invoiceDetailsForm.get('vatPercentage').value}}</p>
        </div>

        <div >
            <p >BTW bedrag</p>
            <p ><abf-display-currency [value]="invoiceDetailsForm.get('invoiceVatValue').value"></abf-display-currency></p>
            <!-- <p  ><abf-display-currency [value]="invoiceDetailsForm.get('invoiceVatValue').value"></abf-display-currency></p> -->
        </div>

        <div >
            <p >Factuurwaarde excl. BTW</p>
            <p ><abf-display-currency [value]="invoiceDetailsForm.get('invoiceTotalValueExclVat').value"></abf-display-currency></p>
            <!-- <p  ><abf-display-currency [value]="invoiceDetailsForm.get('invoiceTotalValueExclVat').value "></abf-display-currency></p> -->
        </div>

        <div >
            <p >Adressering</p>
            <div >
                <img src="../../assets/svgs/sy-notification-verified-16.svg"  />
                <p >De factuur is aan Asset Based Finance NV geaddresseerd.</p>
            </div>
        </div>

        <abf-action-button-green 
        buttonText="Wijzig factuurgegevens" 
        icon="sy-tools-pencil.svg" 
         
        [useRouter]="false"
        (click)="changeInvoiceDetailsHandler()"></abf-action-button-green>
    </div>

    <div *ngIf="showInvoiceDetails">

        

        <form  [formGroup]="invoiceDetailsForm">
            <div >
                <label id="invoiceNumber" for="invoiceNumber">Factuurnummer</label>
                <p  *ngIf="invoiceDetailsForm.get('invoiceNumber').errors && invoiceDetailsForm.get('invoiceNumber').touched">Het factuurnummer is verplicht en mag alleen letters, nummers - en _ bevatten.</p>
                <input type="text" value="" formControlName="invoiceNumber" 
                [ngClass]="{'green-field': invoiceDetailsForm.get('invoiceNumber').valid && invoiceDetailsForm.get('invoiceNumber').touched,  'red-field': invoiceDetailsForm.get('invoiceNumber').invalid && invoiceDetailsForm.get('invoiceNumber').touched}" name="invoiceNumber"  autofocus tabindex="1" />
            </div>

            <div >
                <label id="invoiceDate" for="invoicenumber">Factuurdatum</label>
                <input name="invoiceDate"  formControlName="invoiceDate" type="text" value=""  tabindex="2" />
            </div>

            <div >
                <div  >
                    <label id="invoiceTotalValue" for="invoiceTotalValue">Totale factuurwaarde</label>
                    <p  *ngIf="invoiceDetailsForm.get('invoiceTotalValue').errors && invoiceDetailsForm.get('invoiceTotalValue').touched">De totale factuurwaarde mag alleen nummers, commas en punten bevatten.</p>
                    <div >
                        <div >
                            <span  style="background: white; color: #91ABA9" id="euro-sign">&euro;</span>
                        </div>
                        <input name="invoiceTotalValue" aria-label="total invoice value" aria-describedby="euro-sign"    formControlName="invoiceTotalValue"  type="text" value=""  tabindex="3" />
                    </div>

                </div>
            </div>

            <div >
                <label id="vatPercentage" for="vatPercentage">BTW percentage</label>
                <div>
                    {{ invoiceDetailsForm.get('vatPercentage').value }}%
                    <!-- <button (click)="updateVatPercentage(0)"    [ngClass]="{'active-generic-form-button': invoiceDetailsForm.get('vatPercentage').value === 0}" id="vatTarifOne" tabindex="4" >0%</button>
                    <button (click)="updateVatPercentage(9)"  [ngClass]="{'active-generic-form-button': invoiceDetailsForm.get('vatPercentage').value === 9}"  id="vatTarifTwo" tabindex="5" >9%</button>
                    <button (click)="updateVatPercentage(21)"  [ngClass]="{'active-generic-form-button': invoiceDetailsForm.get('vatPercentage').value === 21}"  id="vatTarifThree" tabindex="6" >21%</button> -->
                </div>
            </div>

            <div >
                <label id="invoiceVatValue" for="invoiceVatValue">BTW bedrag</label>
                <p ><abf-display-currency [value]="invoiceDetailsForm.get('invoiceVatValue').value"></abf-display-currency></p>
            </div>

            <div >
                <label id="invoiceTotalValueExclVat" for="invoiceTotalValueExclVat">Factuurwaarde excl. BTW</label>
                <p >
                    <abf-display-currency [value]="invoiceDetailsForm.get('invoiceTotalValueExclVat').value"></abf-display-currency>
                </p>
            </div>

            <div >
                <label id="invoiceTotalValueExclVat" for="invoiceTotalValueExclVat">Adressering</label>
                <div >
                    <input type="radio" id="radio-item1" formControlName="address" (click)="updateAddress($event)"  style="width: initial; margin-right: 16px;" value="1"  />
                    
                    <label for="radio-item1" tabindex="7"  (click)="updateAddress($event)">De factuur is aan Asset Based Finance NV geaddresseerd.</label>
                </div>
            </div>

            <div  *ngIf="invoiceDetailsForm.get('address').errors || invoiceDetailsForm.get('address').value === ''">
                <div >
                    <img  src="../../assets/svgs/sy-notification-error-round-16.svg" />
                </div>
                <div >
                    <p>De factuur moet aan ABN AMRO Asset Based Finance N.V. zijn geadresseerd, anders kunnen we deze factuur niet verwerken.</p>
                </div>
                
            </div>


            <div>
                <abf-action-button 
                    id="invoiceDetailsSaveChanges"
                    buttonText="Wijzigingen opslaan" 
                    [disabled]="invoiceDetailsForm.status === 'INVALID'"
                    tabindex="8"
                    [useIcon]="false" 
                    [fullWidth]="true"
                    
                    [useRouting]="false"
                    (click)="saveInvoiceDetailsHandler()"
                >
                </abf-action-button>

                <abf-action-button-green 
                    id="invoiceDetailsCancelChanges"
                    buttonText="Annuleren" 
                    tabindex="9"
                    
                  



 [useIcon]="false" 
                    [fullWidth]="true"
                    [useRouter]="false"
                    [bigHeight]="true"
                    (click)="cancelInvoiceDetailsHandler()"
                >
                </abf-action-button-green>
            </div>
            
        </form>
    </div>
</div>

If anyone has any suggetions or explainations I would relly appreciate it.

Cheers!

CodePudding user response:

As already mentioned in the comments, the OnChanges Lifecycle hook only triggers when an @Input changes.

In your case, you could just use a setter instead of using the lifecycle hooks:

  // This will be called when "showInvoiceDetails = someVal" is called
  set showInvoiceDetails(details) {
     this._showInvoiceDetails = details;
     console.log('showInvoiceDetails changed');
  };
  get showInvoiceDetails() { return this._showInvoiceDetails ; }

  private _showInvoiceDetails = false;
  • Related