Westwick
Westwick

Reputation: 2487

angular dependency injection of one service into another for route guard

In my angular app I have two services, one deals with the http layer, and the other is simply a route guard to implement the canActivate method related to the status of the first service. For example:

backend.service:

@Injectable()
export class BackendService {
    private data: any;
    constructor(private http: Http) {
        console.log('backend service constructor hit');
        this.data = 'initial';
    }
    getData() {
        console.log(this.data);
        return this.data;
    }
    setData(data) {
        // http stuff
        this.data = data;
    }
}

routeguard.service:

@Injectable()
export class RouteguardService implements CanActivate {
    constructor(private backendService: BackendService) { }
    canActivate() {
        return this.backendService.getData() !== 'initial';
    }
}

I believe I am providing one of the services in the wrong location? Currently I have both services in the providers array of my app.module. But I can tell with the console.log statements that the backend.service is being new'd up separately when it gets called as part of the routing versus when a component uses it, so the data is different and the data always comes back as 'initial' when checked in the canActivate method despite having it set to something else from a component. Hope I explained that clearly, I'm still new to angular.

Do I need to provide one of the services in a different location or am I doing something else wrong entirely? Thanks for any pointers.

Upvotes: 2

Views: 3697

Answers (2)

Westwick
Westwick

Reputation: 2487

I realized the problem was that I accidentally also included the backend.service in the root app.component providers, which meant that sub components of that would have one instance injected, however the one in my routes file was injected from app.module providers instead, thus the duplicate services and discrepancy in data.

So the solution was to remove the service from the app.component and always have it be provided by app.module instead.

Upvotes: 1

amal
amal

Reputation: 3170

Try to declare the property you want to set in BackendService as a static one. Then use getters and setters to access it. Don't initialize it in the constructor of the service.

@Injectable()
export class BackendService {
    private static data: any = 'initial';
    constructor(private http: Http) {
        console.log('backend service constructor hit');
    }
    get data() {
        console.log(this.data);
        return BackendService.data;
    }
    set data(data: any) {
        // http stuff
        BackendService.data = data;
    }
}

You can then access the private static data value outside using the getters and setters. Like for example in the canActivate guard,

@Injectable()
export class RouteguardService implements CanActivate {
    constructor(private backendService: BackendService) { }
    canActivate() {
        return this.backendService.data !== 'initial';
        // this.backendService.data <-- denotes getter
        // this.backendService.data = 'not-initial'; <-- denotes setter
    }
}

You are providing the services in the right places as understood from the question. Try and see if this fixes it.

Upvotes: 1

Related Questions