-1

I am trying to create a component to show Data.

In my Parent Component I am creating a config obj which will be passed to the ItemViewer Component

export class ProcessListComponent implements OnInit {

process_list: any;
configObj: {};

constructor(public http: HttpClient){}

ngOnInit() {
    // this is the config Obj
    this.configObj = {
        data : this.getAll,
        fields : {
            title : 'Id',
            body :[
                { name : 'Name' , field : 'name'},
                { name: 'Final Material', field : 'final_material'},
                { name : 'Rivision' , field : 'revision'}
            ]
        },
        selectionChanged : this.selectionChangeDetection
    }
}

selectionChangeDetection(item){
    alert(item)
    // some events here, some actions here related to visiblity
}

// function to fetch Obj List
getAll(option: string) {
    // console.log(this)
    return (function(extra_option: string){
        const url: string = 'http://localhost:3000/process_list' + extra_option;
        return this.http.get(url);  // <-- Error comes at this line. How to handle it ??
    })(option);
}
}

I pass this obj to ItemViewer Component and handles it as below:

export class ItemViewerComponent implements OnInit {
@Input() config;
constructor(private http: HttpClient) { }

ngOnInit() {
    this.config.selectionChanged('it works'); // <-- This function works
    this.config.data()
        .subscribe(data => console.log(data)); // <-- Error here
}

}

Now, when I run this I get

ProcessListComponent.html:1 ERROR TypeError: Cannot read property 'http' of undefined at process.list.component.ts:40 at Object.webpackJsonp.../../../../../src/app/features/process/list/process.list.component.ts.ProcessListComponent.getAll [as data] (process.list.component.ts:41) at ItemViewerComponent .webpackJsonp.../../../../../src/app/common/ICV/icv.component.ts.ItemViewerComponent .ngOnInit (item-viewer.component.ts:14) at checkAndUpdateDirectiveInline (core.es5.js:10843) at checkAndUpdateNodeInline (core.es5.js:12341) at checkAndUpdateNode (core.es5.js:12284) at debugCheckAndUpdateNode (core.es5.js:13141) at debugCheckDirectivesFn (core.es5.js:13082) at Object.eval [as updateDirectives] (ProcessListComponent.html:1) at Object.debugUpdateDirectives [as updateDirectives] (core.es5.js:13067)

Now, I know that I am getting this error because this does not have http var of ProcessListComponent.

The same config used to work with $http when I had the application in Angular1.X and I used to pass

 function getAll(option) {
            return (function (ur_option){
                return $http.get('http://XYZ&units=metric&'+ur_option)
            })(option)
        }

Update

Thanks to ConnorsFan& Radonirina Maminiaina: below code worked

getAll = (option: string) => {
   return ((extra_option: string) => {
       const url: string = 'http://localhost:3000/process_list' + extra_option;
       return this.http.get(url);
    })(option);
 }
Shashank Vivek
  • 16,888
  • 8
  • 62
  • 104
  • 2
    In addition to defining the function returned by `getAll` as an arrow function, you should also declare `getAll` itself as an arrow function: `public getAll = (option: string) => { ... }` (because `getAll` is used as a callback). Or set it in the configuration like this: `data : (option: string) => { ... }`. – ConnorsFan Mar 24 '18 at 15:01
  • 1
    @ConnorsFan : Thank you so much. `getAll = (option: string) =>` did the trick. – Shashank Vivek Mar 24 '18 at 16:45

1 Answers1

3

You have to use arrow function if you want to keep this context.

Arrows are a function shorthand using the => syntax. They are syntactically similar to the related feature in C#, Java 8 and CoffeeScript. They support both expression and statement bodies. Unlike functions, arrows share the same lexical this as their surrounding code. If an arrow is inside another function, it shares the “arguments” variable of its parent function.

getAll(option: string) {
    // console.log(this)
   return ((extra_option: string) => {
       const url: string = 'http://localhost:3000/process_list' + extra_option;
       return this.http.get(url);  // <-- Error comes at this line. How to handle it ??
    })(option);
 }

Or you have to save this into a variable:

getAll(option: string) {
    // console.log(this)
    let $this = this;
    return (function(extra_option: string){
        const url: string = 'http://localhost:3000/process_list' + extra_option;
        return $this.http.get(url);  // <-- Error comes at this line. How to handle it ??
    })(option);
}

You can find more explaination here.

UPDATE: When you call your getAll method, you will do this:

this.getAll('options')()

Or am I wrong?

So why just do it:

getAll(option: string) {
    const url: string = 'http://localhost:3000/process_list' + option;
    return this.http.get(url);
}

Or I don't understand what are you want to do?

Radonirina Maminiaina
  • 6,958
  • 4
  • 33
  • 60