I'm trying to bind an async value to one of my Aurelia templates, and obviously all I get is [object Promise] in return.
I found this article http://www.sobell.net/aurelia-async-bindings/ which excellently explains how to solve this problem using a binding behavior which looks like this:
// http://www.sobell.net/aurelia-async-bindings/
export class asyncBindingBehavior {
bind (binding, source) {
binding.originalUpdateTarget = binding.updateTarget;
binding.updateTarget = a => {
if (typeof a.then === 'function') {
binding.originalUpdateTarget('...');
a.then(d => {
binding.originalUpdateTarget(d);
});
}
else {
binding.originalUpdateTarget(a);
}
};
}
unbind (binding) {
binding.updateTarget = binding.originalUpdateTarget;
binding.originalUpdateTarget = null;
}
}
This works perfectly when the promise resolves with a string or other non-object-like variable.
But what if my promise resolves with an object? How would I go about accessing the property I need inside that object?
Because if I do: ${object.property & async} inside my template then it will fail as object.property isn't a promise - only object is.
I added a bit of a hack that allows me to specify a property as an argument to async, like this: ${object & async:'property'} and updated my binding behavior as such:
// http://www.sobell.net/aurelia-async-bindings/
export class asyncBindingBehavior {
bind (binding, source, property) {
binding.originalUpdateTarget = binding.updateTarget;
binding.updateTarget = a => {
if (typeof a.then === 'function') {
binding.originalUpdateTarget('...');
a.then(d => {
if (property) {
binding.originalUpdateTarget(d[property]);
}
else {
binding.originalUpdateTarget(d);
}
});
}
else {
binding.originalUpdateTarget(a);
}
};
}
unbind (binding) {
binding.updateTarget = binding.originalUpdateTarget;
binding.originalUpdateTarget = null;
}
}
But this feels very much like a hack to me, and it also won't allow me to access any deeper properties like object.parent.child.
I also found this (rather old) issue on GitHub: https://github.com/aurelia/templating/issues/81 where they use a getValue method. I've never heard of this method and trying to use it fails so I'm not sure how that works at all...
Any ideas?
You could sidestep your conundrum by specifying a function as the third parameter, giving the flexibility to do much more than simple property extraction.
You could write something like this :
export class asyncBindingBehavior {
bind (binding, source, transformer="default") {
binding.originalUpdateTarget = binding.updateTarget;
binding.updateTarget = a => {
if (typeof a.then === 'function') {
binding.originalUpdateTarget('...');
a.then(d => binding.originalUpdateTarget(transformFunctions[transformer](d)));
} else {
binding.originalUpdateTarget(a);
}
};
}
unbind (binding) {
binding.updateTarget = binding.originalUpdateTarget;
binding.originalUpdateTarget = null;
}
}
The transformFunctions lookup would be necessary(?) due to the way Aurelia bindings are specified as HTML-ebbedded or template directives (ie all params must be String). Unless Aurelia offers a better way better way to "pass a function" (Value Converters?), you would write something like this :
export var transformFunctions = {
default: (d) => d,
transform1: (d) => d.someProperty,
transform2: (d) => d.someProperty.someOtherProperty,
transform3: someFunction,
transform4: someOtherFunction.bind(null, someData);
}
Of course, you would give the functions better names.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With