I have an input signal which I take and set as attribute but in browser I see an error
this.width is not a function
export class SkeletonComponent implements OnInit {
readonly width = input<string>('');
ngOnInit(): void {
if (isPlatformServer(this.platformId)) {
return;
}
const host = this.host.nativeElement;
host.style.setProperty('--app-skeleton-width', this.width() || '100%');
The reason you might be getting this error, is because the ngOnInit
is execute in a context (scope) somewhere other than your component scope, The code shared does not seem to have any issues, but you can achieve this feature using lesser code using @HostBinding
or host
demonstrated below.
host
property of @Component
params:@Component({
...
host: {
'style.--app-skeleton-width': 'width()',
},
})
Here we can define the CSS property using 'style.--app-skeleton-width'
and execute the signal inside a string.
We can then use the transform
property to set a default value.
readonly width = input<string, string>('', {
transform: (value: string) => value || '100%',
});
Or we can simply define the width as the default value.
readonly width = input<string>('100%');
@HostBinding
decorator and execute the signal inside:We can define the @Hostbinding
and return the signal value.
@HostBinding('style.--app-skeleton-width')
get skeletonWidth() {
// if (isPlatformServer(this.platformId)) {
// return;
// }
return this.width() || '100%';
}
We can achieve this using the two methods, below is a working example for your reference:
import { Component, HostBinding, input } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
@Component({
selector: 'app-child2',
template: `
this is the child
<div style="width: var(--app-skeleton-width)">
I got my width from --app-skeleton-width
</div>
`,
styles: [
`div {
background-color: lightblue;
}`,
],
host: {
'style.--app-skeleton-width': 'width()',
},
})
export class Child2 {
readonly width = input<string, string>('', {
transform: (value: string) => value || '100%',
});
}
@Component({
selector: 'app-child',
template: `
this is the child
<div style="width: var(--app-skeleton-width)">
I got my width from --app-skeleton-width
</div>
`,
styles: [
`div {
background-color: lightblue;
}`,
],
})
export class Child {
readonly width = input<string>('');
@HostBinding('style.--app-skeleton-width')
get skeletonWidth() {
// if (isPlatformServer(this.platformId)) {
// return;
// }
return this.width() || '100%';
}
}
@Component({
selector: 'app-root',
imports: [Child, Child2],
template: `
<app-child [width]="'500px'"/>
<br/>
<br/>
<app-child2 [width]="'300px'"/>
`,
})
export class App {
name = 'Angular';
}
bootstrapApplication(App);