Chris Rutherford
Chris Rutherford

Reputation: 1672

Angular Service Parameter undefined

I have a service that is called in a component and it was working before I tried to implement some code reuse tactics, but now the http client isn't coming in as defined. The component calls the appropriate function like this:

//actions object that maps the request on the object
//split between the different areas of the app.
serviceActions: {[name: string]: {[name: string]:(...args: any[]) => Observable<any>}} = {
    'Customer':{
        GetCategories: this._service.GetCategories,
    }
    'Admin':{...}
};
// source string referenced in the function call
source: string = 'Customer';

//the actual call being made
this.serviceActions[this.Source].GetCategories(...).subscribe(...)

This code is calling a function on a service that takes http as a parameter:

//service constructor:
 constructor(private httpClient: Http) { }
//service method:
public GetCategories(showAll = false, parentId = 0): Observable<Array<SelectModel>> {
        let link = AppSettings.API_COMMON_CATEGORIES;
        let params: URLSearchParams = new URLSearchParams();
        params.set('showAll', showAll.toString());
        params.set('parentId', parentId != null ? parentId.toString() : null);
        let requestOptions = new RequestOptions();
        requestOptions.search = params;

        return this.httpClient.get(link, requestOptions).map(response => {
            let result = JSON.parse(response.json());
            let list = new Array<SelectModel>();
            let caregories: Array<any> = result;

            caregories.forEach(category => {
                list.push(this.CreateSelectModel(category));
            });

            return list;
        });
    }

This was working fine when the service method was called directly, but now that I've implemented the serviceActions object, it's saying cannot read property get of undefined

what gives?

Upvotes: 0

Views: 1755

Answers (1)

Chris Rutherford
Chris Rutherford

Reputation: 1672

The issue stems from the fact that packing functions on the object dereferences this from the class where it was defined. To get around this, we should wrap the function package in another anonymous function passing along the parameters.

So instead of:

serviceActions: {[name: string]: {[name: string]:(...args: any[]) => Observable<any>}} = {
    'Customer':{
        GetCategories: this._service.GetCategories,
    }
    'Admin':{...}
};

it should really be:

serviceActions: {[name: string]: {[name: string]:(...args: any[]) => Observable<any>}} = {
    'Customer':{
        GetCategories: (params) => this._service.GetCategories(params),
    }
    'Admin':{...}
};

to preserve the reference to this in the class.

Upvotes: 1

Related Questions