2

I am trying to create a file upload component, and display the text file contents in a textarea in the browser for editing before processing.

My inputs looks like this

<input type="file" process-file/>
<textarea id="file-text"
     ng-model="fileContent">
</textarea>

I have a directive that correctly reads the file contents

app.directive('processFile', [function () {
    return {
        link: function (scope, element, attrs) {
            element.on('change', function  (evt) {
                var files = evt.target.files;

                var reader = new FileReader();
                reader.onload = function(e) {
                    var text = e.target.result
                    console.log(text); // contents are correctly displayed
                    scope.fileContent = text;  // this does not work
                    $scope.fileContent = text; // nor does this
                    $("#file-text").text(text) // or this
                };

                reader.readAsText(files[0]);
            });
        }
    }
}]);

I need to inject the file content into that textarea but all attempts seem to fail. How can I do that?

Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
Vinny Gray
  • 477
  • 5
  • 18

2 Answers2

1

Custom event considered as event runs out of angular context. After firing such event angular digest cycle system doesn't get intimated to update its bindings. You have to kick off digest cycle manually to sync up binding. You could use $timeout here to run digest cycle.

Code

element.on('change', function  (evt) {
    var files = evt.target.files;
    var reader = new FileReader();
    reader.onload = function(e) {
        var text = e.target.result
        console.log(text); // contents are correctly displayed
        $timeout(function(){
            scope.fileContent = text;
        },0);
    };

    reader.readAsText(files[0]);
});
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • 1
    How about application of `scope.apply` ? – Rayon Dec 20 '16 at 20:14
  • 1
    @Rayon It may lead to conflict into the currently running digest cycle, whereas if you do `$timeout` it will run digest cycle safely.. It will never ever conflict with already running digest cycle.. more convenient would be using `$scope.$applyAsync()` – Pankaj Parkar Dec 20 '16 at 20:15
0

This is how you change value of a textarea:

document.getElementById('myTextarea').value = '';

or like this in jQuery:

$('#myTextarea').val('');

Where you have

<textarea id="myTextarea" name="something">This text gets removed</textarea>

How to change the Content of a <textarea> with Javascript

So should have this in your onload function:

$("#file-text").val(text);

Or this in your html file:

<textarea id="file-text">
    {{fileContent}}
</textarea>
Community
  • 1
  • 1
Alic
  • 638
  • 6
  • 27