2

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.

Westwick
  • 2,367
  • 3
  • 28
  • 51

2 Answers2

1

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.

amal
  • 3,140
  • 1
  • 13
  • 20
1

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.

Westwick
  • 2,367
  • 3
  • 28
  • 51
  • 1
    Just to point out, everytime you inject this service anywhere in your app, it will create a new data property associated to it as part of the constructor call. Just be aware of it, if that is desired, then no issues. Otherwise, or in other words, if you wanna have a singleton-property associated with your injectable service that can be accessed from within multiple modules, then you will have to declare it with `static`. – amal Sep 21 '17 at 19:06