Aurelia store v1 and service classes

I have sucessfully used aurelia store and really like it. Suddenly I stumbled on something I can not make work:

I have two classes CaseStateAdapter and InboxStateAdapter that both implment interface IStateAdapter. Depending on “reasons” the start of the application might do this:

aurelia.container.registerSingleton("StateAdapter", CaseStateAdapter);

or this

aurelia.container.registerSingleton("StateAdapter", InboxStateAdapter);

The CaseStateAdapter looks likt this (no constructor). The InboxStateAdapter looks similar

@connectTo()
export class CaseStateAdapter implements IStateAdapter {
    public state: IAppState;

I then try to eject the StateAdapter into a component like below:

@inject(Store,AppActions,PlatinaServiceBase, "StateAdapter",CreateDeedAdapterBase,"WebPartContext")
@connectTo()
export class CreateDeedDetails {

In the attached method i must set the value like below.

this.stateAdapter.state = this.state; // stateAdapter.state is "undefined"

Why is the stateAdapter.state not set? Must it be a component? Is this possible without setting the state value like above?

I think what you need to do is to have an abstract class such as StateAdapter rather than an interface. And then you register the singletons conditionally. Accordingly, you need to change the @inject as well and use the StateAdapter base class directly.

Additional info: what you are trying to do can be achieved via using a Symbol as injection token, but that might bring unwarranted complexity for you.

1 Like

connectTo is for components only as it works using their lifecycle methods. I’d suggest you create a manual subscription instead

1 Like

I acutally tried the abstract class first but as @zewa666 pointed out this class is not a component and has no attached/bind methods that will be called. I will try to start the subscription manually. I think I have tried that too, but I will do it with more conviction.

OMG! That worked great. I would bet an ice cream that I have already tried that. If anyone else wants to do the same, below is my adapter.

@inject(Store)
export class CaseStateAdapter implements IStateAdapter {
    public state: IAppState;
    private subscription:Subscription;
    
    constructor(private store: Store<IAppState>)
    {
        this.subscription = this.store.state.subscribe(
            (state) => { this.state = state; }
          );
    }
2 Likes

And if anyone wonders, the interface and the base class both work equally well with the store injected into its implemented classes.

there’s just one more issue here. the subscription returns a disposable object which you have to dispose by yourself. now if the service lives for the whole apps duration its no problem, but if it gets destroyed and rebuild, e.g on router navigation, make sure to cleanup so you avoid potential memleaks

1 Like

Spot on, thank you for reminding me. :slight_smile:

I have added the TODO comment regarding that. But in this case the class “StateAdapter” is registered as a singleton on the container so, at least as I understand it, the class will last until the page is completly reloaded. If I have a antoher scenario in the future where it is required I will try to post my solution here.

3 Likes