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">€</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;