Silently modifying a @bindable property?

Hello, guys,
Is there a way to change the value of a @bindable property without it triggering the propertyChanged callback?
For instance, in the case of observables I can do the following thing:

export class Test {

_prop; //The underlying value used by @observable
@observable prop;

propChanged(){
    console.log("Prop changed");
}

constructor() {
     this.prop = 'foo';   //Will fire propChanged()
     this._prop = 'bar';  //Will not fire propChanged() but prop will update.
}

}

… which is really nice. However observables are not… bindable. So I can’t use the expression

< test prop.bind="…" >< /test >

… unless I make prop @bindable instead of @observable (right?). But then if I make prop @bindable I can’t seem to find a way to silently change it’s underlying value from code without triggering the propChanged method.

Any tips are greatly appreciated.
Thank you!

You can do:

import {bindable, ObserverLocator} from 'aurelia-framework'

export class MyClass {
  static inject = [ObserverLocator]

  @bindable mySilentProp

  constructor(observerLocator) {
    this.observerLocator= observerLocator;
  }

  silentlySetValue(newSilentValue) {
    this.observerLocator.getObserver(this, 'mySilentProp').currentValue = newSilentValue;
  }
}

However, bindable is designed to work with templating, so you cannot do it in the constructor, as the observer won’t be ready for you to fiddle with.

2 Likes

Thank you for your reply!

There is no problem if it doesn’t work in the constructor. I would set the value in this manner only after the components are attached anyway.
This seems to set the underlying value but unlike @observable, it doesn’t refresh the values in the view(s).

Here’s a gist of it:

Ok I didn’t read your question clearly.

You can do it like in this gist https://gist.run/?id=80d03e1da000624f3cd46a6f6e697c20

basically do with observer.callSubscribers(newValue, oldValue)

If you can describe your scenario here, maybe some folks can help you to put together a better solution than touching the internal of Aurelia like this

2 Likes

Awesome, this seems to be it. Thank you so much!

My scenario is the following: I have a table with two controls. A text input for setting the page number and a dropdown for choosing how many rows to be displayed on a page.

Each of these 2 controls has an “onChange” event which automatically calls the refresh method on the table which goes to the server and queries for new results.
After the response from the server comes back, I may find that the page I asked for was too big (because let’s in the mean-time rows were deleted). So the server gave me the last page of results… At this point I have the data for the last page, but I need to correct the value for the current page displayed in my input (and other places). But if I do

this.pageNumber = newPageNumber;

… this will cause the pageNumberChanged method to be called again, making an unnecessary request to the server.

A better design could be to not update whenever a single property is being changed. Instead implement an update method and only update whenever it is being called.

1 Like