0

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?

4
  • This is an unrelated note, but you should be using the HttpClient class, rather than Http; Http has been deprecated for a while. For example, you don't need to json.parse in your map with HttpClient Commented Sep 6, 2019 at 14:59
  • It's also a good idea to follow the TypeScript/JavaScript conventions when naming methods: it's strongly advised to name methods in camelCase instead of PascalCase as with what you would do in dotnet or C languages. Commented Sep 6, 2019 at 15:02
  • First a few things, 1. The app is written in Angular 4.3, and cannot be upgraded currently, was originally written with Http and I need to think the process through before migrating. 2. We're primarily a C# shop, so Pascal Case is preferred with us. Commented Sep 6, 2019 at 15:14
  • Also can confirm that it's putting it in a dictionary like this that's causing the issues. Commented Sep 6, 2019 at 15:57

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.