Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ValueConverter): enable signal #626

Merged
merged 4 commits into from
Oct 8, 2017

Conversation

bigopon
Copy link
Member

@bigopon bigopon commented Oct 2, 2017

This PR:

  • Addresses Value converters should support triggering updates #353 Value converters should support triggering updates
  • Has potential integration with BindingSignaler in templating-resources, where signaling in there will also trigger here, treating signal universal
  • Still needs tests (WIP)
  • Usage:
export class LocaleValueConverter {
  signals: string | string[] = 'locale-changed'
}

// usage
import { ConverterSignaler } from 'aurelia-binding';
ConverterSignaler.signal('some-thing');

@jdanyow @EisenbergEffect @thomas-darling @davismj

@jdanyow
Copy link
Contributor

jdanyow commented Oct 5, 2017

It would be nice if we could unify this API with the existing binding signaler API. I think there's an opportunity here to tie signaling in at a lower level, in the "connect" phase and refactor the existing signaling logic to leverage the existing binding machinery related to property observation.

Today, the ValueConverter expression class looks like this:

export class ValueConverter extends Expression {
  ...
  ... other methods ...
  ...
  connect(binding, scope) {
    let expressions = this.allArgs;
    let i = expressions.length;
    while (i--) {
      expressions[i].connect(binding, scope);
    }
  }
}

I think we could change it to something like this:

import { connectBindingToSignal } from './signals';

export class ValueConverter extends Expression {
  ...
  ...
  ...
  connect(binding, scope) {
    const expressions = this.allArgs;
    let i = expressions.length;
    while (i--) {
      expressions[i].connect(binding, scope);
    }
    // new stuff:
    const signals = binding.lookupFunctions.valueConverters(this.name).signals;
    if (signals === undefined) {
      return;
    }
    i = signals.length;
    while (i--) {
      connectBindingToSignal(binding, signals[i]);
    }
  }
}

aurelia-binding - signals.js (new module)

const signals = Object.create(null);

export function connectBindingToSignal(binding, name) {
  if (!signals.hasOwnProperty(name)) {
    signals[name] = 0;
  }
  binding.observeProperty(signals, name);
}

export function signalBindings(name) {
  if (signals.hasOwnProperty(name)) {
    signals[name]++;
  }
}

Then our BindingSignaler class in templating-binding would reuse the new signalBindings function. We should probably mark it obsolete and inform users to switch over to signalBindings.

The signal binding behavior would become much simpler by reusing then new connectBindingToSignal function.

What do you think?

@bigopon
Copy link
Member Author

bigopon commented Oct 5, 2017

You meant we determine signals based on BindingBehavior / ValueConverter -> signals properties ?
Edit: i got what you meant. Sounds better to me. Will change / push another PR in templating resources

@bigopon
Copy link
Member Author

bigopon commented Oct 6, 2017

@jdanyow Things looks a lot neater now. very cool 👍 💯

  • templating-resources also ready.
  • What do you think about the tests ?

Copy link
Contributor

@jdanyow jdanyow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests look good, nice work.

src/ast.js Outdated
return;
}
// support both input type 'signal' & ['signal-1', 'signal-2']
signals = Array.isArray(signals) ? signals : [signals];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a really hot path. Let's remove this line entirely to ensure the connect overhead remains minimal.

I don't think supporting string & array is necessary, just more to document & maintain. If we were to do that here's a good spot to perform the normalization, but again, I would prefer to keep the API surface small and strict:

initialize(container, target) {
this.instance = container.get(target);
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdanyow All done as suggested. Learnt to be more careful with connect. About the API, 99% of usage will be a single signal, I do think we need to support normalisation, but I'll let you make the call after this got merged. What do you think ?

@jdanyow jdanyow merged commit f6ad52a into aurelia:master Oct 8, 2017
@EisenbergEffect
Copy link
Contributor

EisenbergEffect commented Oct 8, 2017 via email

@bigopon
Copy link
Member Author

bigopon commented Oct 8, 2017 via email

@bigopon bigopon deleted the binding-value-converter-signal branch October 8, 2017 20:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants