Class.bind with object

Is it correct that this is not a valid class binding syntax:

<span class.bind="{ 'class1': prop1 == 'x', 'class2': prop2 == 'y' }"></span>

How should I write this?

The following approach does not look very elegant to me:

<span class="${prop1 == 'x' ? 'class1' : ''} ${prop2 == 'y' ? 'class2' : ''}"></span>
1 Like

Thats correct. There a lot of flexibility here though

one way is using a custom attribute to populate classes.

// classes-custom-attribute.ts
import { dynamicOptions, inject } from 'aurelia-framework';
import { getLogger} from 'aurelia-logging';

@dynamicOptions
@inject(Element)
export class ClassesCustomAttribute {
  logger = getLogger('classes');

  constructor(private element: Element) { }

  propertyChanged(name: string, newValue: boolean, oldValue: boolean) {
    this.logger.debug('changed', name, newValue, oldValue);
    newValue ? this.element.classList.add(name)
      : this.element.classList.remove(name);
  }
}

and then use it like

<template>
  <require from="./classes-custom-attribute"></require>

  <div class="static-class" classes="class1.bind: prop1 == 'x'"></div>
</template>

another way with a custom attribute

// classes-custom-attribute.ts
import { inject } from 'aurelia-framework';
import { getLogger} from 'aurelia-logging';

@inject(Element)
export class ClassesCustomAttribute {
  logger = getLogger('classes');

  constructor(private element: Element) { }

  value: Record<string, any>;

  valueChanged(newValue: any, oldValue: any) {
    this.logger.debug('changed', newValue, oldValue);

    Object.keys(newValue).forEach(key => {
      newValue[key] ? this.element.classList.add(key)
        : this.element.classList.remove(key);
    });
  }
}

and use it like

<template>
  <require from="./classes-custom-attribute"></require>

  <div class="static-class" classes.bind="{class1: prop1 == 'x', class2: prop2 == 'y'}"></div>
</template>

or use a value converter

// filter-class-value-converter.ts
export class FilterClassValueConverter {
  toView(newValue: Record<string, any>): string {
    if (!newValue) return '';

    return Object.keys(newValue)
      .filter(key => {
        return newValue[key];
      })
      .join(' ')
  }
}

and use it like

<template>
  <require from="./filter-class-value-converter"></require>

  <div class="static-class ${{class1: prop1 == 'x', class2: prop2 == 'y'} | filterClass }"></div>
  or
  <div class.bind="{class1: prop1 == 'x', class2: prop2 == 'y'} | filterClass "></div>
</template>
5 Likes

you could make any of the above a global resource too so you don’t have to require in each of your templates

1 Like

Au2 can handle this natively. Basically anything clsx can do plus more.

2 Likes

Many thanks to all of you!

1 Like