Search code examples
data-bindingaurelia

Aurelia creating a Binding Behaviour that wraps SignalBindingBehaviour


I've currently got a simple Value Converter which uses momentjs to convert Dates to strings:

export class MomentValueConverter {
  public toView(value: Date, format: string): string {
    return moment(value).format(format);
  }
}

However, wherever I use it I end up having to combine it with the aurelia-translation-signal so that its updated if the user changes the current language.

${fileSaved | moment:'ll LTS' & signal:'aurelia-translation-signal'} 

How do I instead create a Binding Behavior that automatically takes care of the signalling from aurelia-translation-signal?

Then I could use it like:

${fileSaved & moment:'ll LTS'}

Solution

  • There is a good example in aurelia-i18n library, https://github.com/aurelia/i18n/blob/master/src/t.js#L89-L122

    import {ValueConverter} from 'aurelia-binding';
    import {SignalBindingBehavior} from 'aurelia-templating-resources';
    
    export class TBindingBehavior {
      static inject = [SignalBindingBehavior];
    
      constructor(signalBindingBehavior) {
        this.signalBindingBehavior = signalBindingBehavior;
      }
    
      bind(binding, source) {
        // bind the signal behavior
        this.signalBindingBehavior.bind(binding, source, 'aurelia-translation-signal');
    
        // rewrite the expression to use the TValueConverter.
        // pass through any args to the binding behavior to the TValueConverter
        let sourceExpression = binding.sourceExpression;
    
        // do create the sourceExpression only once
        if (sourceExpression.rewritten) {
          return;
        }
        sourceExpression.rewritten = true;
    
        let expression = sourceExpression.expression;
        sourceExpression.expression = new ValueConverter(
          expression,
          't',
          sourceExpression.args,
          [expression, ...sourceExpression.args]);
      }
    
      unbind(binding, source) {
        // unbind the signal behavior
        this.signalBindingBehavior.unbind(binding, source);
      }
    }
    

    UPDATE: Signals are internally supported by value converters already http://aurelia.io/docs/binding/value-converters#signalable-value-converters

    import {signalBindings} from 'aurelia-framework';
    
    signalBindings('locale-changed');
    
    
    export class FlightTimeValueConverter {
      signals = ['locale-changed'];
    
      toView(date) {
        return date.toLocaleString(window.currentLocale);
      }
    }