Skip to content

Instantly share code, notes, and snippets.

@niieani
Last active June 24, 2016 23:56
Show Gist options
  • Save niieani/9300029424327b4aa282fa7f5a1e8b89 to your computer and use it in GitHub Desktop.
Save niieani/9300029424327b4aa282fa7f5a1e8b89 to your computer and use it in GitHub Desktop.
Aurelia Binding Proxies Proposition

Binding Proxy concept

@inlineView(`<template>
  <input value.bind="firstName">
</template>`)
class Example {

  @bindingProxy firstName(bindingValueSetter) {
    // function run when the binding is bound, returns an object:
    return {
      // function run when the value of the binding is changed from the View:
      next: (value) => bindingValueSetter(value),
      // function run when the binding is unbind:
      dispose: () => { }
    }
  }
}

This would solve the other uses of binding functions. Much cleaner than a getter with a getObserver method and setter.

then we could do things like:

@inlineView(`<template>
  ${timer}
</template>`)
class Example {

  @bindingProxy timer(bindingValueSetter) {
    let i = 0;
    let timer = setInterval(() => bindingValueSetter(i++), 1000);
    return {
      dispose: () => clearInterval(timer)
    }
  }
}

A self-contained one-way, stateless timer binding. 😄

Binding Proxies like that would really help implement alternative state management systems for Aurelia, like Redux or Cycle.js.

Dynamic Binding Proxy

Then there could be a variation of a Binding Proxy, a Dynamic Binding Proxy:

@inlineView(`<template>
  <input value.bind="firstName">
</template>`)
class Example {

  @dynamicBindingProxy((promise, bindingValueSetter) => {
    promise.then(promise => bindingValueSetter(value));
  })
  firstName = Promise.resolve('Jeremy');
}

or with Observables:

@dynamicBindingProxy((observable, bindingValueSetter) => {
  let observer = observable.subscribe((next) => bindingValueSetter(next));
  return {
    dispose: () => observer.unsubscribe()
  }
})
observable = Rx.Observable.interval(1000);

Really easy to make an abstraction then for the common things like Promises or Observables:

function promiseHandler(promise, bindingValueSetter) {
  promise.then(value => bindingValueSetter(value));
}

function observableHandler(observable, bindingValueSetter) {
  let observer = observable.subscribe((next) => bindingValueSetter(next));
  return {
    dispose: () => observer.unsubscribe()
  }
}

function subjectHandler(rxSubject, bindingValueSetter) {
  // sending values both to and from an Observable (an Rx Subject)
  let observer = rxSubject.subscribe((next) => bindingValueSetter(next));
  return {
    next: value => rxSubject.next(value),
    dispose: () => observer.unsubscribe()
  }
}

class Example {
  @dynamicBindingProxy(promiseHandler) firstName = Promise.resolve('Jeremy');
  @dynamicBindingProxy(observableHandler) seconds = Rx.Observable.interval(1000);
}
@niieani
Copy link
Author

niieani commented Jun 24, 2016

Actually, a better name could be a "Binding Intercept" since we're intercepting the binding here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment