Reputation: 5688
I have a property selectedOption
on the state of my Aurelia Store, which can be changed via actions. I want to observe/subscribe to any changes to this property on the state. My problem is the subscription within the BindingEngine
doesn't work because every time you change the state, you create a new copy of the state, therefore the subscription no longer works.
Here is my example:
import { Disposable, BindingEngine, autoinject } from "aurelia-framework";
import { connectTo, dispatchify } from "aurelia-store";
@autoinject()
@connectTo()
export class Holiday {
subscription: Disposable;
state: any;
constructor(private bindingEngine: BindingEngine) {
}
async updateState()
{
await dispatchify(changeSelectedOption)();
}
attached() {
this.subscription = this.bindingEngine
.propertyObserver(this.state, 'selectedOption')
.subscribe((newValue, oldValue) => {
console.log("something has changed!")
});
}
}
export class State {
selectedOption: number = 0;
}
export const changeSelectedOption = (state: State) => {
let updatedState = { ...state };
updatedState.selectedOption++;
return updatedState;
}
store.registerAction("changeSelectedOption", changeSelectedOption);
The first time, my subscription will work and the console will log "something has changed!" as the state is the same object, but it won't work after.
Another solution I could use would be to have a computed property like so:
@computedFrom("state.selectedOption")
get selectedOptionChanged()
{
return console.log("something has changed!");
}
This is a hack, and this computed won't ever be triggered as it is not bound to anything in the HTML.
For context, I want to trigger a server call every time the selectedOption
property changes.
What can I do to receive all updates from the property on the state?
Upvotes: 1
Views: 855
Reputation: 2603
The thing here is that the state observable exposed by the Store is a RxJS stream. So with the advent of the new "multi-selector" feature for connectTo you could create two bindings. By implementing a hook called selectorKey
Changed, in your sample selectedOptionChanged
it would get called on every change of said property.
@connectTo({
selector: {
state: (store) => store.state, // the complete state if you need
selectedOption: (store) => store.state.pluck("selectedOption")
}
})
class MyVM {
...
selectedOptionChanged(newState, oldState) {
// notification about new state
}
}
Instead of store.state.pluck("selectedOption")
you can also experiment with additional conditions when to notify about changes like adding distinctUntilChanged
etc.
Read more about multi-selectors in the updated docs.
Alternatively if you don't want to use the connectTo decorator, simply use the state property and create another subscription
Upvotes: 2