I’m developing a standalone component in Angular 20 and I’m getting this error:
ERROR TypeError: ctx.widgetSize is not a function
at SanctionWidgetComponent_Template (sanction-widget.component.html:1:1)
Context
Here is my SanctionWidgetComponent:
import { Component, input, SimpleChanges } from '@angular/core';
import { SanctionData } from './model/sanction-data';
import { Size } from '../../../../features/dashboard/models/modal-widget.model';
import { TimeSlot } from '../../../../shared/shared.model';
import { FormatNumberPipe } from '../../../../shared/pipes/format-number.pipe';
@Component({
selector: 'app-sanction-widget',
templateUrl: './sanction-widget.component.html',
styleUrls: ['./sanction-widget.component.scss'],
standalone: true,
imports: [FormatNumberPipe]
})
export class SanctionWidgetComponent {
data = input<SanctionData>({
date: '19/09/2024',
year: '2025',
amount: 200000,
totalAmount: 500000,
trendPercentage: 4,
trendAmount: 50000
});
widgetSize = input<Size>(Size.XS);
selectedLocation = input<string>('');
timeslot = input<TimeSlot>();
validData = false;
protected readonly Size = Size;
}
HTML Template
I removed the CSS classes and replaced mds-text and mds-icon with standard HTML tags. The @if structure remains unchanged:
@if (widgetSize() === Size.XS) {
<div>
<span>Collected {{ data()?.year }}</span>
<div>{{ data()?.amount ?? 0 | formatNumber }} €</div>
<span>Total to collect: {{ data()?.totalAmount ?? 0 | formatNumber }}€</span>
</div>
}
@if (widgetSize() === Size.S) {
<div>
<div>
<div>
<span>Collected {{ data()?.year }}</span>
<div>{{ data()?.amount ?? 0 | formatNumber }} €</div>
</div>
<span>Total to collect: {{ data()?.totalAmount ?? 0 | formatNumber }}€</span>
</div>
<div>
<span>[icon]</span>
<span>{{ data()?.trendAmount ?? 0 | formatNumber }}€</span>
</div>
<div>
<span>[icon]</span>
<span>{{ data()?.trendPercentage ?? 0 | formatNumber }}€</span>
</div>
</div>
}
This is the parent component, where I dynamically set all inputs:
loadComponent(): void {
const viewContainerRef = this.appWidgetHost.viewContainerRef;
viewContainerRef.clear();
// Ottieni il tipo di componente dal servizio
const componentType = this.widgetFactory.getComponent(this.widgetType);
if (componentType) {
const componentRef = viewContainerRef.createComponent(componentType);
this.currentComponentRef = componentRef;
// Passa i dati se esistono
this.widgetDataService
.getWidgetConfig(this.widgetType)
.pipe()
.subscribe({
next: widgetConfig => {
if (widgetConfig && widgetConfig.data) {
componentRef.setInput('data', widgetConfig.data);
componentRef.setInput('widgetSize', this.widgetSize);
componentRef.setInput('timeslot', this.getWidgetInfoByType(this.widgetType).timeSlot);
componentRef.setInput('selectedLocation', widgetConfig.selectedLocation);
this.cdr.markForCheck();
}
}
});
} else {
console.error(`Componente per ${this.widgetType} non trovato.`);
}
}
Problem
Even though widgetSize is correctly set in the parent component, Angular throws:
ctx.widgetSize is not a function
I read that this can happen when trying to call a property as a function, but I’m using @if with widgetSize() according to the template syntax. If I remove widgetSize attribute, the problem involved also other inputs, like "data" object.
Questions
- What is the correct way in Angular 20 to use
@ifwith a property likewidgetSize? - Should I call
widgetSize()or just usewidgetSize? - How can I make the template work without causing this error?
widgetSizedefined on your parent component, and how do you create thecomponentRef?Inputand notinputfrom@angular/core. So whatinputare you actually using in your component?