No access to class properties (and injected services) in virtual scroll header functions

As I have to deal with large lists, I heavily rely on Virtual Scroll lists. To group my items, I use a custom header function. So my code is like
Template:

<ion-list [virtualScroll]="filteredData" [headerFn]="dataHeaderFn">
  <ion-item-divider *virtualHeader="let groupheader">
    {{groupheader}}
  </ion-item-divider>
  <button ion-item *virtualItem="let data"> ... </button>
</ion-list>

And my corresponding typescript:

someProperty;
...
constructor( private myService: MyService,...) { ... }
...
dataHeaderFn (dataItem, dataIndex, data) {
  let propertyTest = this.someProperty; //runtime error!
  let serviceTest = this.myService.doSomething(); //runtime error!
}

Now my problem is, that I cannot access my class properties or my injected services within the header function “dataHeaderFn”: this.someProperty and this.myService are both undefined within the function context.

I know that it once worked but broke somewhere during the last framework updates.
Has anybody an idea how to overcome this issue?

Thanks!

[edit]
When debugging the header function with chrome, I see that “this” within its context is of type “ComponentRef_” and has a property “_component”, which finally refers to my component and its properties/services.

Simply saying “this._component.someProperty” doesn’t compile, so I assume I will need some sort of type casting for “this”.

[edit 2]
With

import { ComponentRef_ } from '@angular/core/src/linker/component_factory';
...
dataHeaderFn (dataItem, dataIndex, data) {
  let propertyTest = (this as any as ComponentRef_<any>)._component.someProperty;
}

I’m said that

[ts] Property '_component' is private and only accessible within class 'ComponentRef_<C>'.

So is it really impossible to gain access to class properties within a custom header function?

[edit 3]
I opened an issue for this, because it once worked and in my case is essential for the handling of my virtual scroll lists.

I would try to make dataHeaderFn a closure. It might be as simple as:

dataHeaderFn = (dataItem, dataIndex, data) => {
  // "this" should be set properly in here
};
6 Likes

@rapropos suggestion would work. This isn’t an Ionic thing at all (hence them closing the issue), it’s a JavaScript thing. You are passing in a function to be called by something else, it won’t have any access to wherever the function came from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Creating_a_bound_function

Alternatively you could do:

myHeaderFn() {
    const thisReference = this;
    return function(record, recordIndex, records) {
      let propertyTest = thisReference.someProperty;
      let serviceTest = thisReference.myService.doSomething();
    }
  } 

And just call myHeaderFn in the html instead of passing it (add parentheses to the end).

But IMO @rapropos solution is cleaner.

1 Like

Thank you, smart, clean and works!

Thank you for your suggestion! I eventually opened an issue for this because my code for the header function worked in a previous framework version (RC4?) without any problems and I didn’t find a reference to this in the following changelogs.