Skip to content

Instantly share code, notes, and snippets.

@qtuan
Last active May 13, 2016 04:01
Show Gist options
  • Save qtuan/2c7e40e88d1d3c18e9d2bca6be438b47 to your computer and use it in GitHub Desktop.
Save qtuan/2c7e40e88d1d3c18e9d2bca6be438b47 to your computer and use it in GitHub Desktop.
Aurelia "cancellable" custom binding behavior
<template>
<require from='./cancellable'></require>
<div>
Name: ${name}
Age: ${age}
<button click.delegate="edit()">Edit</button>
</div>
<div if.bind="editing">
<h3>Cancellable edit</h3>
Name: <input value.bind="name & cancellable">
Age: <input value.bind="age & cancellable">
<div><button click.delegate="save()">Save</button>
<button click.delegate="cancel()">Cancel</button></div>
</div>
<div if.bind="editing">
<h3>Instant edit</h3>
Name: <input value.bind="name">
Age: <input value.bind="age">
</div>
</template>
export class App {
constructor() {
this.name = 'John';
this.age = 20;
this.editing = false;
this.saved = false;
}
edit() {
this.saved = false;
this.editing = true;
}
save() {
this.saved = true;
this.editing = false;
}
cancel() {
this.saved = false;
this.editing = false;
}
}
import {inject} from 'aurelia-dependency-injection';
import {BindingEngine} from 'aurelia-binding';
@inject(BindingEngine)
export class CancellableBindingBehavior {
constructor(bindingEngine) {
this.bindingEngine = bindingEngine;
}
bind(binding, scope) {
let value;
let modified = false;
let cancellable = {
originalUpdateSource: binding.updateSource,
originalUpdateTarget: binding.updateTarget,
};
// 1. Intercept "updateSource" to redirect write to a hidden value storage
binding.updateSource = (val) => {
value = val;
modified = true;
};
// 2. Intercept updateTarget" so that can observe change from original source
binding.updateTarget = (val) => {
value = val;
modified = false;
cancellable.originalUpdateTarget.call(binding, val);
}
// 3. Observe the "saved" event to copy back to original source
let bindingContext = scope.bindingContext;
cancellable.subscription = this.bindingEngine.propertyObserver(bindingContext, 'saved')
.subscribe((newValue, oldValue) => {
if (newValue && modified) {
cancellable.originalUpdateSource.call(binding, value);
}
});
binding.cancellable = cancellable;
}
unbind(binding, scope) {
binding.updateSource = binding.cancellable.originalUpdateSource;
binding.updateTarget = binding.cancellable.originalUpdateTarget;
binding.cancellable.subscription.dispose();
binding.cancellable = null;
}
}
<!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://cdn.rawgit.com/jdanyow/aurelia-bundle/v1.0.3/jspm_packages/system.js"></script>
<script src="https://cdn.rawgit.com/jdanyow/aurelia-bundle/v1.0.3/config.js"></script>
<script>
System.import('aurelia-bootstrapper');
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment