javascripthtmlangularjsfile-uploadjs-xlsx

How can I read a file from an HTML input with js-xlsx?


I have an angular application where I am trying to read and parse a .xlsx file resorting to the js-xlsx JavaScript library. However I am having trouble opening the file on the JavaScript side.

On my html I have a simple input of type file that opens a file chooser where the user can choose an appropriate file. I had trouble using angular directives to send the file to a function on my controller, because ng-change would not update when the user chose a file only when the button of the input is pressed. I ended up having to resort to a mixture of plain old JavaScript together with some angular by adding 'onchange="angular.element(this).scope().handleFile(this)"' to my input.

add-quotation.html:

<div class="container-fluid" ng-controller="addQuotationController">
...  
<input type="file" id="file" class="" onchange="angular.element(this).scope().handleFile(this)">
...
</div>

This solved my problem of not being able to send the file from the HTML to the JavaScript side of things. However, I'm having trouble opening the file. I have tried many examples from the official documentation but I haven't succeeded in making it work. This is my current code:

add-quotation.component.js:

$scope.handleFile = function(e) {
    var files = e.target.files;
    var i,f;
    for (i = 0, f = files[i]; i != files.length; ++i) {
        var reader = new FileReader();
        var name = f.name;
        reader.onload = function(e) {
            var data = e.target.result;

            var workbook = XLSX.read(data, {type: 'binary'});

            /* DO SOMETHING WITH workbook HERE */
        };
        reader.readAsBinaryString(f);
    }
}

I tried to debug and found out that the file does indeed get into the method but then an exception occurs when trying to access "e.target.files;"

getting into the function

trying to access e.target.files

I'm completely lost in how to fix this and the examples that I've seen are of no help. What am I doing wrong?


Solution

  • You are looking for wrong object rather you should be using e.files. This is because e represents the <input> element; aka the value of this in your onchange attribute: onchange="angular.element(this).scope().handleFile(this)"

    $scope.handleFile = function(e) {
    
     console.log(e.files);
     var files = e.files;
     var i,f;
     for (i = 0, f = files[i]; i != files.length; ++i) {
        var reader = new FileReader();
        var name = f.name;
        reader.onload = function(e) {
            var data = e.target.result;
    
            var workbook = XLSX.read(data, {type: 'binary'});
    
            /* DO SOMETHING WITH workbook HERE */
        };
        reader.readAsBinaryString(f);
    }
    
    }