Search code examples
javascriptaureliaaurelia-templating

How to evaluate an Aurelia interpolation expression outside a view?


In Aurelia, let's say I have a string containing an interpolation expression "Today at ${value | date: 'time'}" and some object representing the binding context for this { value: new Date() }. Is there any way to, outside of a view, just take that string and that object, and get the resulting formatted string, i.e. "Today at 13:44"?

I looked at the tests, but they all involve creating an HTML element, binding, and then unbinding - I'm wondering what the performance overhead of all that might be, and whether there is an easier way to achieve this? It would be really awesome if there was a light-weight way to just evaluate such a string against a context object, without setting up and tearing down bindings, etc.


Solution

  • Here's an example: https://gist.run?id=a12470f6e9f7e6a605b3dd002033fdc7

    expression-evaluator.js

    import {inject} from 'aurelia-dependency-injection';
    import {ViewResources} from 'aurelia-templating';
    import {Parser, createOverrideContext} from 'aurelia-binding';
    
    @inject(Parser, ViewResources)
    export class ExpressionEvaluator {
      constructor(parser, resources) {
        this.parser = parser;
        this.lookupFunctions = resources.lookupFunctions;
      }
    
      evaluate(expressionText, bindingContext) {
        const expression = this.parser.parse(expressionText);
        const scope = {
          bindingContext,
          overrideContext: createOverrideContext(bindingContext)
        };
        return expression.evaluate(scope, this.lookupFunctions);
      }
    }
    

    app.js

    import {inject} from 'aurelia-dependency-injection';
    import {ExpressionEvaluator} from './expression-evaluator';
    
    @inject(ExpressionEvaluator)
    export class App {
      message = 'Hello World!';
    
      constructor(evaluator) {
        this.message = evaluator.evaluate('foo.bar.baz | test', { foo: { bar: { baz: 'it works' } } });
      }
    }
    

    Edit

    I missed the fact that you need to parse an interpolation expression, not a regular binding expression...

    There's an example of this in aurelia-validation: https://github.com/aurelia/validation/blob/master/src/implementation/validation-message-parser.ts