19

I am using the FileReader Interface and it’s asynchronous method readAsText() to read a local text file, After that when the onload event is called, I try to read my file, my source code is something like the following:

export class ReadFileComponent {
   text: string;

   readFile(): void {
     let reader=new FileReader();
     reader.onload = function(e) {
        this.text=reader.result;
     }
     reader.readAsText(file);   
   }
}

compilation is failed because Property "text" does not exist on type "FileReader"

I think this is due to the EventListener interface does not accept objects ,

did someone please solve this kind of issue?

thanks guys,

da45
  • 271
  • 1
  • 3
  • 11

2 Answers2

54

If you want to use this inside the callback, use an arrow function, otherwise it won't work

reader.onload = (e) => {
    this.text=reader.result;
}

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Günter Zöchbauer
  • 490,478
  • 163
  • 1,733
  • 1,404
  • No it works fine with console.log(reader.result), the problem is with "this" means currentTarget property is of type EventTarget and not type of class ReadFileComponent – da45 Jan 19 '17 at 09:04
  • 4
    That's why you need to use `()=>` instead of `function ()`. Arrow functions ensure `this` within the callback keeps pointing at the current class. – Günter Zöchbauer Jan 19 '17 at 09:06
  • right.. maybe [this](http://stackoverflow.com/questions/22939130/when-should-i-use-arrow-functions-in-ecmascript-6) will clarify it – Suraj Rao Jan 19 '17 at 09:09
  • Unfortunately, it seems that the ‘ reader.onload’ part does not work, in production [after ng build — prod]. The reason for this, is that the non Angular version is: reader.onload = function(evt) { } Because this does NOT use an arrow function, the parent context is not passed in. In Angular we need access to the parent context, hence the use of arrow functions. What actually happens, using an arrow function, is that the entire ‘onload’ function is passed to ‘reader.result’. – Charles Robertson May 28 '18 at 10:33
  • @CharlesRobertson not sure what you mean. My answer uses arrow function – Günter Zöchbauer May 28 '18 at 21:47
  • Yes. I realise this, but what I meant, is that the Vanilla JS version works partly because it uses a non arrow function. But I also found out that the other reason it fails in Angular is because there is a bug in zone.js. A temporary fix for this can be found here: https://stackoverflow.com/questions/45542462/angular-4-x-cordova-filereader-fails-silently-white-screen-of-death/45542463?noredirect=1#comment88157606_45542463 – Charles Robertson May 29 '18 at 21:54
  • 1
    let FileReader: new() => FileReader = ((window as any).FileReader as any).__zone_symbol__OriginalDelegate; let reader = new FileReader(); This allows the event to be passed in to 'onload' correctly, which in turn, allows us to use 'event.target.result' – Charles Robertson May 29 '18 at 21:58
4

You are using a regular javascript function here:

 reader.onload = function(e) {
        this.text=reader.result;
     }

The this belongs to the function not your class.

Use arrow function

reader.onload = (e)=> {
            this.text=reader.result;
         }

Or

self = this;
 reader.onload = function(e) {
        self.text=reader.result;
     }
Suraj Rao
  • 28,186
  • 10
  • 88
  • 94