javascriptangulartypescriptangular-signals

Using Angular Signals with HostBinding to update style?


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?


Solution

  • 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 also utilize signals

    if change in signal results in expression's output change, host element will be updated

    @Component({
      host: {
        // bind to classes
        'class': 'flex flex-col', // static string
        '[class]': '"flex " + "flex-col"', // for expressions use [] and quotes
        '[class.active]': 'this.isActive()',   // <-- signal. 'this.' is optional 
    
        // bind to some specific props
        '[tabIndex]': 'isDisabled() || isActive() ? -1 : 0',
        
        // bind to any attribute
        '[attr.aria-disabled]': 'isDisabled()',
        '[attr.aria-selected]': 'isActive()',
        '[attr.data-id]': 'id', // render component's any field value as host attr
    
        // bind to style
        '[style.display]': 'isEnabled() ? "flex" : "none"',
        '[style.width]': 'progressSignal() + "px"'
        '[style.width.px]': 'progressSignal()'     // or directly to units
    
        // bind css vars
        '[style.--component-color]': 'color()',
    
        // bind to events
        '(focus)': 'activateOption()', // method on component class
        '(click)': 'select($event)',
        '(contextmenu)': 'false', // preventDefault() is applied
        '(document:pointerdown)': 'doSomething($event)', // to global
      }
      // ... 
    })
    export class SomeComponent {
    // ...