cssangularsignalsng-classangular-signals

Using Angular Signals with classes


I have found some behaviour that I can't understand. If I've got a bunch of styles applied like this:

.monkey-ion-item{
 // Country Variant XXXX Not working after upgrade!
  &.monkey-variant-search-list-country {
    .monkey-icon {
      color: var(--ion-color-success, green);
    }
  }

And then in the html:

<ion-item
  [ngClass]="classes"
  class="monkey-ion-item"
  ...

Why does the following work fine:

  get classes() {
    return `monkey-variant-${this.variant()} ` +
    `monkey-input-type-${this.type()} ` +
    'monkey-input';
  }

Doing this successfully adds all of the listed classes to the ion-item element that they are added to in the template. And they show up perfectly in the properties -> classlist when I inspect the DOM.

but the signal approach to the same fails:

  classes: Signal<string[]> = computed(() => [
    `monkey-variant-${this.variant()}`,
    `monkey-input-type-${this.type()}`,
    'monkey-input',
  ]);

In the case where it fails, if I inspect the DOM, I can see some reference to the classes, but it's clearly not right!

ng-reflect-ng-class=\"[Computed: monkey-variant-sear

I'm migrating code over to use signals and was under the impression that this was the "right" way to do things. But I'm clearly missing something here?!


Solution

  • Using the computed is best. Since the output is memoized, if the inputs do not change, the output is not recomputed.

    classes: Signal<string[]> = computed(() => [
      `monkey-variant-${this.variant()}`,
      `monkey-input-type-${this.type()}`,
      'monkey-input',
    ]);
    

    You just need to execute the computed. Since computed is a function we have to execute it to access the value inside.

    <ion-item
      [ngClass]="classes()"
      class="monkey-ion-item"
      ...