Reputation: 47090
In a app-test
component I have the following:
@Input( { transform: booleanAttribute})
reverse: boolean = false;
@HostBinding('style.flex-direction')
direction: string = this.reverse ? 'column-reverse' : 'column';
And so if the designer applies the reverse
attribute to app-test
like this:
<app-test reverse></app-test>
Then Angular should set style="flex-direction: column-reverse"
on the app-test
element.
And I'm wondering how to use Angular signals so that when reverse
is set to true, direction will be set to column-reverse
. Thoughts?
Upvotes: 16
Views: 8299
Reputation: 3776
you can bind to host properties, attributes, classes, styles and events with host section of @Component decorator
host option is inherited from @Directive decorator, so you can use this technic also with directives.
host accepts binding dictionary with values being javascript expressions that can utilize signals
@Component({
// ommited for brevity
host: {
// bind to classes
'class': 'flex flex-col',
'[class.active]': 'isActive()', // <-- signal
// bind to some specific props
'[tabIndex]': 'isDisabled() || isActive() ? -1 : 0', // <-- also
// bind to any attribute
'[attr.aria-disabled]': 'isDisabled()',
'[attr.aria-selected]': 'isActive()',
// bind to style
'[style.display]': 'isEnabled() ? "flex" : "none"',
'[style.flex-direction]': 'isReversed() ? "column-reverse" : "column"',
'[style.width]': 'progressSignal() + "px"'
'[style.width.px]': 'progressSignal()' // or directly to units
'[style.width.%]': 'progressSignal() * 100'
// bind css vars
'[style.--component-color]': 'color()',
// bind to events
'(focus)': 'activateOption()',
'(click)': 'select($event)',
}
})
export class SomeComponent {
// ommited
}
Upvotes: 21
Reputation: 1972
I would use an effect for that.
All these examples use a getter in the hostBinding but the thing with getters is that they're actually functions that will be executed every time change detection needs to "check" if the value has changed.
I would just do:
@Component({...})
public class MyComponent {
public reverse = input<boolean>(false);
@HostBinding('style.flex-direction') public reversedStyling = false;
constructor(){
effect(() => this.reversedStyling = this.reverse());
}
}
I'm sure the angular team will introduce a signal-based version of HostBinding and HostListeners sooner rather than later though.
Upvotes: 8
Reputation: 47090
My current project was on Angular 16, so this is what I ended up with (Since input
is for Angular 17+):
@Input( { transform: booleanAttribute})
reverse:boolean = false;
@HostBinding('style.flex-direction')
get direction() { return this.reverse ? 'column-reverse' : 'column' }
Upvotes: 0
Reputation: 55669
This is being discussed in this issue. Currently the combination of @HostBinding
and signals is not supported.
The workaround for this is to use a getter:
reverse = input.required<boolean>();
@HostBinding('attr.style.flex-direction')
get direction() { return this.reverse() ? 'column-reverse' : 'column' }
Upvotes: 11
Reputation: 2332
You can do the following:
@Component({
selector: 'app-child',
standalone: true,
template: 'My name (red is {{ red() }})',
})
export class AppChildComponent {
red = input(false);
@HostBinding('style.color')
get color() {
return this.red() ? 'red' : 'green';
}
}
And in the container component:
@Component({
selector: 'app-root',
standalone: true,
imports: [AppChildComponent],
template: `
<app-child [red]="true"></app-child>
`,
})
export class App {
}
Working example here
Upvotes: 1