If you have ever found that you need to observe some property, or an expression of a custom element or a custom attribute, and call a method when the value of that property or expression change, then you probably have looked at something like the ObserverLocator or BindingEngine. This is not always ergonomic, and could result it forgotten subscription. We are trying to evaluate an official API for v2 around this, and thanks to @jods4 for api idea, we’ve got a watch decorator: https://www.npmjs.com/package/aurelia-watch-decorator
Is this intended to be a replacement for the @observable decorator? Or will it complement @observable? Will there be an overview of the functional differences between @watch and @observable and when to apply which?
For v1, the @watch decorator can do everything the @observable decorator can do, in an opposite way. For v2, they will be complementary, there’ some planned new capabilities for the @observable decorator.
I am not sure what you mean with “in an opposite way”. As far as I can see, @watch and @observable have almost the same purpose, but with different functional (and interesting) capabilities.
Furthermore, you also say that @watch will be able to observe expressions. Can it also observe property getters? Will it use a dirty checking observation strategy by default in such cases where such an expression or property getter is dependent on another class member? Will it be possible to combine @watch with @computedFrom to avoid such dirty checking?
Yes, I agree that could be useful in some scenarios. However, I doubt if this new watching/observing functionality is directly related to Aurelia’s binding features. I think these are two separate concerns.
But I guess it would be pretty straightforward to implement some debouncing/throttling functionality yourself as you desire, or simply use a library that already implements such functionality (like Lodash or so).
for big flaw with regular get + computedFrom is:
get logic are only applied if you have something that is bound to it in the view.
but sometimes you want a piece of logic to run and change based on other values.
but you have nothing in particular to be bound to.
(this is not some weird example, I really had this kind of problem in a real app).
I wish I knew about watch then. it would solve the problem so nicely…
For the sake of clarity, while @watch decorates a method, and @observable wraps a property, the effect is essentially the same: watch a property and invoke a method. If that’s correct, I’d like to hear use-cases were this is helpful. Other than providing the convenience of avoiding wrapping calls like:
With @observable, you observe a single property and react to it.
With @watch, you observe an expression (v1), so it’s more ergonomic in some cases:
@watch('some.expression')
myMethod() {
}
// with typescript, you can also have intellisense:
@watch((abc: Abc) => abc.props.counter, newValue => 'new value is of type number')
class Abc {
props = { counter: 0 }
}
@bigopon areyou planing on adding the watch decorator in aurelia 2?
this is realy a core feature that should be embeded in the framework. rather than an external dependency.
EDIT:
i just re-read the first message here and got my answer.
thanks again.
When using @observable on properties, I am quite often only interested in the newValue parameter in the corresponding *Changed callback function. I consider it an elegant advantage to have the possibility to avoid specifying the oldValue parameter when I don’t need it.
So my question is if the instance argument is important enough to specify it as the first argument. It would be a pity if I would always have to specify a parameter for it, even when I do not need it in most cases.
Being able to specify multiple @watch decorators for the same method is very powerful. But could it be useful to be able to determine which expression triggered the decorated method? (This would probably require an additional name argument to the @watch decorator, which is passed as a fourth argument to the decorated method or the callback.)
But if this would become too complicated, I could certainly settle with decorating different methods instead (thus avoiding multiple @watch decorators on the same method).