Aurelia Binding Limits

Does Aurelia have limits in watching bindings contains methods? See the following example:

Binding is working when using get syntax:

get isEnabledAsGet() {
    return this.isEnabled;
}

Binding is not working when using a function:

isEnabledAsFunction() {
    return this.isEnabled;
}
1 Like

Yes. By default, Aurelia binding assumes method calls in template are pure. Which means if they don’t have changes in their parameter, their call result remain the same.
What you can do is to pass the parameter to your call to observe for changes:

<div>${getFullName(firstName, lastName)}</div>

with

  getFullName(firstName, lastName) {
    return firstName + lastName;
  }
1 Like

OK thanks for your quick feedback.

1 Like

I still have problems to make it work. I’ve created another little example on codepen:

How would you write this to ensure, that all quotes are getting updated when adding a value?

1 Like

The method getQuote actually has 2 dependencies: values, and value. And for values, it needs to observe as an array. That is why the existing code doesn’t work. I have a working example here https://codepen.io/bigopon/pen/jObBwVe

What I did was to give Aurelia more information about what to observer, using an identity value converter, and passing the expression that will make Aurelia observe array values

Thanks a lot for your help. As we come from AngularJs we are used to automatic updates and we have some difficulties to rewrite our components.

I extended my example with a change value button: https://codepen.io/elitastic/pen/bGVWQvL.

The quotes are not updated when changing the value. I know that I could change getQuote(value) to getQuote(value.prop) to fix it. Unfortunately our components are more complex than this example and it’s not that easy to find and solve these situations, are there best practices how such problems are usually realized in Aurelia?

We are a bit afraid that our code could be prone to errors due to these binding characteristics. We have no problems to rewrite our code, but we just don’t know how, at the moment.

Besides that, we are very excited so far about the simplicity of Aurelia and would love to use it in our projects.

1 Like

I see. So there’s more than a dependency or 2 that need to be observed to update the bindings there. In this case, I’d say we use a signal instead, as observing all those dependencies automatically isn’t easy from the view, without some manual code. There’re two ways to signal bindings to update:

Using binding signaler, as in official doc here http://aurelia.io/docs/binding/binding-behaviors#signal

Using a value converter parameter to signal binding, with an increment from view model after changes. Like in this example https://gist.dumber.app/?gist=9c1947889d491e24c438e30b1e3f315a

Those two are the most lightweight solutions for your case, there’s can be another one, where we observe the properties of each array element, it depends.

Btw, try https://gist.dumber.app it’s easier for doing Aurelia POC / demo apps than other online tools.

Thanks again for your great support, really appreciate it!

From your everyday experience with Aurelia, don’t you often have situations where a binded value does not update itself because you forgot to use a signal? We are clearly biased here because of our experiences with AngularJS. What we’ve found so far, is to keep components small to limit these kind of situations. Is this your key recipe or how do you avoid using signal? I’m afraid that using signals all around is leading to error-prone code? Or are my concerns of no means at all?

I’m still a bit suprised about this behaviour in general as we almost never had problems with the performance of AngularJS, where there isn’t this limitation of updating bindings (as far as I know Vue doesn’t have this limitation, too).

Don’t get me wrong, I am still very positively surprised by Aurelia. But these binding properties make me worry a bit about migrating our codebase… :slight_smile:

1 Like

From a developer ergonomic perspective: Yes, this’ a surprise. As there’s no easy way to automatically observe all the properties used for a binding with a view. It’s probably understandable - since automatically observing everything could be expensive.

From a reverted ergonomic perspective: well, having a simple signal mechanism that only requires 1 property observation to update a bunch of stuff is pretty ok-ish. Not the best, but pretty efficent.

That said, there’s a way for automatic observation with this. GitHub - bigopon/aurelia-deep-computed: A plugin for declaring deep/shallow computed observation. It’ll be easier, though maybe depends on scenarios and situation to say how much easier.

This is acknowledged, and is fixed in v2 with the use of Proxy. For IE11, it’ll need to be done in similar manner like the above plugin.

In my project, I’ve mostly gone with signal mechanism, and local ones via value converter like you saw. So I don’t need to care about naming & clashing.

EDIT: I missed this

in general as we almost never had problems with the performance of AngularJS, where there isn’t this limitation of updating bindings (as far as I know Vue doesn’t have this limitation, too).

AngularJS always updates everything, and Vue by default always observes everything, so neither of them runs into this. Aurelia, on the other hand, try to avoid going either way.

Maybe I can create a plugin that support this syntax for observation:

@computedFrom('myArray[_].prop')
get someValue() {
    ...
}

The expression myArray[_].prop means treat when myArray is an array, for every element of myArray (the [_] part), observe the prop property

If you’re up for a… “creative” solution, you could get method results to be updated by providing a dirty/generation parameter that you then update/increment whenever you want the methods to be recomputed. So something along the lines of (untested)

class App {
  constructor() {
    this.values = [50, 150];
    this.counter = 0;
  }
  add() {
    this.values.push(50);
    this.counter++;
  }
  getQuote(value, counter) {
    return (100 / this.values.reduce((sum, value) => sum + value, 0)) * value + this.values.length;
  }
}

and

    <span>${value}, quote: ${getQuote(value, counter)}%</span>

EDIT: Come to think of it, you probably don’t even need to have a view model property or method parameter, just calling the method with a value that’s updated (could even be a calculation) when a change occurs should be enough. So just doing

<span>${value}, quote: ${getQuote(value, values.length)}%</span>

should be enough if you’re only doing additions and removals.