Skip to content

Instantly share code, notes, and snippets.

@niieani
Last active June 25, 2016 11:33
Show Gist options
  • Save niieani/46721ca0c56d56d09a931ae8bf524b49 to your computer and use it in GitHub Desktop.
Save niieani/46721ca0c56d56d09a931ae8bf524b49 to your computer and use it in GitHub Desktop.
Aurelia Observer Test
<template>
<require from="./binding-intercept"></require>
<binding-intercept-example if.bind="show"></binding-intercept-example>
</template>
export class App {
show = true;
// constructor() {
// setInterval(() => this.show = !this.show, 2000);
// }
}
<template>
<p>Promise Binding: ${somePromise} <button click.delegate="changePromise()">Change Promise</button></p>
<br/><br/>
<p>Obj Promise Binding (work in progress): ${someObjPromise.value}</p>
<br/><br/>
<p>Timer Binding: ${someTimer}</p>
<br/><br/>
Two Way Binding (see console):<br/>
<input value.bind="firstName">
<button click.delegate="changeFirstName()">Change Name to Bazyli</button>
</template>
export class BindingInterceptExample {
@bindingIntercept(promiseBinding) somePromise = new Promise(resolve => setTimeout(() => resolve('Hello!'), 2000));
changePromise() {
this.somePromise = new Promise(resolve => setTimeout(() => resolve('Awesome!'), 2000));
}
@bindingIntercept(promiseBinding) someObjPromise = new Promise(resolve => setTimeout(() => resolve({value: 'Obj Promise!'}), 2000));
@bindingIntercept(timer) someTimer;
@bindingIntercept(twoWayIntercept) firstName = 'Rob';
changeFirstName() {
this.firstName = 'Bazyli';
}
}
function promiseBinding(promise, bindingValueSetter) {
promise.then(value => bindingValueSetter(value));
}
function timer(any, bindingValueSetter) {
let i = 0;
let timer = setInterval(() => bindingValueSetter(i++), 1000);
return {
dispose: () => clearInterval(timer)
}
}
function twoWayIntercept(value, bindingValueSetter) {
console.log('ViewModel changed value to:', value);
bindingValueSetter(value);
return {
next: (value) => console.log('View changed value to:', value)
}
}
function bindingIntercept(interceptor) {
return function interception(definition, propertyName, descriptor) {
let viewModelValue = descriptor.initializer && descriptor.initializer();
let observersBound = new Set();
function updateObservers(viewModelValue) {
for (let observer of observersBound) {
if (observer.interceptorInstance.dispose)
observer.interceptorInstance.dispose();
observer.interceptorInstance = interceptor(viewModelValue, observer.binding.updateTarget.bind(observer.binding)) || {};
}
}
const observableGetter = function() { return viewModelValue; }
observableGetter.getObserver = function(targetClass) {
return {
subscribe: function(context, binding) {
this.interceptorInstance = interceptor(viewModelValue, binding.updateTarget.bind(binding)) || {};
binding.updateTarget(undefined);
observersBound.add(this);
this.binding = binding;
binding.sourceExpression.assign = (scope, value) => {
// assignement coming from View
if (this.interceptorInstance.next)
this.interceptorInstance.next(value);
}
},
unsubscribe: function(context, binding) {
if (this.interceptorInstance.dispose)
this.interceptorInstance.dispose();
observersBound.delete(this);
}
}
}
delete descriptor.writable;
delete descriptor.initializer;
Object.defineProperty(descriptor, 'set', {
value: function (viewModelValue) {
// assignement coming from ViewModel:
updateObservers(viewModelValue);
viewModelValue = viewModelValue;
}
});
Object.defineProperty(descriptor, 'get', {
value: observableGetter
});
}
}
<!doctype html>
<html>
<head>
<title>Aurelia</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body aurelia-app>
<h1>Loading...</h1>
<script src="https://jdanyow.github.io/rjs-bundle/node_modules/requirejs/require.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/config.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/bundles/aurelia.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/bundles/babel.js"></script>
<script>
require(['aurelia-bootstrapper']);
</script>
</body>
</html>
export function twoWayExample(definition, propertyName, descriptor) {
let val = descriptor.initializer && descriptor.initializer();
let bindingsBound = new Set();
const observableGetter = function() {
return val;
}
observableGetter.getObserver = function(targetClass) {
return {
subscribe: function(context, binding) {
bindingsBound.add(binding);
binding.updateTarget(val);
console.log('subscribed', this, targetClass, binding);
binding.sourceExpression.assign = function(scope, value) {
// assignement coming from View
console.log('View set:', value);
val = value;
}
},
unsubscribe: function(context, binding) {
bindingsBound.delete(binding);
}
}
}
delete descriptor.writable;
delete descriptor.initializer;
Object.defineProperty(descriptor, 'set', {
value: function (value) {
// assignement coming from ViewModel:
val = value;
// update bindings
for (let binding of bindingsBound) {
binding.updateTarget(value);
}
console.log('ViewModel set:', value);
}
});
Object.defineProperty(descriptor, 'get', {
value: observableGetter
});
return descriptor;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment