How can I display a text files contents in a textarea? - javascript

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?

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]);
});

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>

Related

Javascript inline script onchange not working

i'm having a problem on making my code to adjust to my web server, because of the security purposes, all inline javascript code to my html is not allowed.
everything is already okay i'm just having a hard time converting my other code to pure javascript
Here is my existing code,,,
<label class=qrcode-text-btn><input type=file accept="image/*" capture=environment id="openQRCamera" tabindex=-1></label>
the original code is this
<label class=qrcode-text-btn><input type=file accept="image/*" capture=environment onchange="openQRCamera(this);" tabindex=-1></label>
the onchange is not working because it is inline in the html.
this function needs to open a camera and detect if there is a qr that exists.
here is what i have now on converting it.
document.querySelector("#openQRCamera").addEventListener('onchange', (node) => {
var reader = new FileReader();
reader.onload = function() {
node.value = "";
qrcode.callback = function(res) {
if(res instanceof Error) {
alert("There is no QR detected");
} else {
node.parentNode.previousElementSibling.value = res;
}
};
qrcode.decode(reader.result);
};
reader.readAsDataURL(node.files[0]);
});
here is the original code
function openQRCamera(node) {
var reader = new FileReader();
reader.onload = function() {
node.value = "";
qrcode.callback = function(res) {
if(res instanceof Error) {
alert("There is no QR detected");
} else {
node.parentNode.previousElementSibling.value = res;
}
};
qrcode.decode(reader.result);
};
reader.readAsDataURL(node.files[0]);
}
i am using this website as my source of code, everything is working fine in my localhost, but the server is just strict, and i think that's normal for all the websites.
https://www.sitepoint.com/create-qr-code-reader-mobile-website/
i just been stuck and try to do other solution like adding event listener, and append of input just by using jquery, but it's not working. thanks in advance.
The event listener you are using is faulty, instead of listenning to 'onchange' you have to listen to 'change' like so:
document.querySelector("#openQRCamera").addEventListener('change', () => {
//remove the node as parameter and get it with javascript:
var node = document.getElementById('openQRCamera');
..

Javascript Input Event Fire Twice

I want to upload an Excel file through the browser and I am showing this file. However sometimes there is an error and I need to change some columns in the Excel file and I want to upload the same file. The event is firing just one time because filename is the same. How can I solve this problem? I want to upload the same file and I want the event to fire twice.
document.getElementById('upload').addEventListener('input', handleFileSelect, false);
var handleFileSelect = function(evt) {
var files = evt.target.files; // FileList object
var xl2json = new ExcelToJSON();
xl2json.parseExcel(files[0]);
console.log(evt)
};
<input id="upload" type=file name="files[]">
I tried
$("#upload").unbind("input").bind("input",handleFileSelect)
and
document.getElementById('upload').addEventListener('change', handleFileSelect, false)
You should use the onChange event.
var el = document.getElementById('upload');
el.onchange = function() {
// your code...
};
I solved this problem. I added this code in my function
evt.target.value = null;

angularjs - ng-file-upload not binding model to dynamically created HTML form

I want to upload an image file from dynamically generated HTML form using ng-repeat.
I am using ng-file-upload module to upload the single image file (https://github.com/danialfarid/ng-file-upload).
When I am uploading file from static HTML its working fine.
But when I try to upload the file from dynamically generated HTML then it wont work as expected. The file is not uploading and also giving error in firefox console as follows :
Error: Argument 2 of FormData.append is not an object.
The form is successfully submitted if we assign ng-model of file control set to null.
for example; if
<input name='img' type='file' value='' ng-model='data.imageFile' 'ngf-select' accept='image/*' />
and
$scope.data.imageFile = null;
then other parameters will submitted by HTTP service and store to database normally but file will not going to upload.
Is any way to assign file object to the input[type=file] in this case of dynamically generated HTML??
The code PLUNKER is created here
http://plnkr.co/edit/S7hnVJnuDjWUMQ6PYewk?p=preview
Yes there is a way to assign input type=file to dynamically generated html. Not just dynamically generated when the page load, but also when adding new input type=file via angular. I just did this and it worked!!! and I'm so excited I post all the tricks here. All I'm asking in return is please Vote up when you get it working in your solution. Both the question and the Answer are at 0 point now, but I can prove that this is a working solution.
<input type="file" class="form form-control" placeholder="Section Image" file-model2="fileUploadFile2[getImageIndex(c.ChapterNbr, $index)][$index]" />
Notice that have two dimension array and this input=file goes inside ng-repeat within ng-repeat, dynamically added when user presses the +Add button.
on the angular side, in getImageIndex:
var chIndex = 0;
var sIndex = 0;
$scope.getImageIndex = function (chNbr, sectionNbr) {
for (var i = 0; i < $scope.chapters.length; i++) {
if ($scope.chapters[i].ChapterNbr == chNbr) {
chIndex = i;
sIndex = sectionNbr;
return i;
};
};
};
This is purely to get the indexes (first and second dimension, specific to my setup).
I use directive posted somewhere in StackOverflow that I'm thankful for, to actually get the file bytes and info, and it goes like this:
.directive('fileModel2', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.bind('change', function (e) {
$parse(attrs.fileModel2)
.assign(scope, element[0].files[0]);
scope.$apply();
scope.getFile2(scope.$eval(attrs.indexNumber));
});
}
};
}])
.factory('fileReaderFactory', function ($q, $log) {
return {
onLoad: function (reader, deferred, scope) {
return function () {
scope.$apply(function () {
deferred.resolve(reader.result);
});
};
},
onError: function (reader, deferred, scope) {
return function () {
scope.$apply(function () {
deferred.reject(reader.result);
});
};
},
onProgress: function (reader, scope) {
return function (event) {
scope.$broadcast("fileProgress",
{
total: event.total,
loaded: event.loaded
});
};
},
getReader: function (deferred, scope) {
var reader = new FileReader();
reader.onload = this.onLoad(reader, deferred, scope);
reader.onerror = this.onError(reader, deferred, scope);
reader.onprogress = this.onProgress(reader, scope);
return reader;
},
readAsDataURL: function (file, scope) {
var deferred = $q.defer();
var reader = this.getReader(deferred, scope);
reader.readAsDataURL(file);
return deferred.promise;
}
}
}
);
The directive triggers getFile2, which executes the Filereader to read the bytes fore previewing the image.
Finally, to preview the image:
$scope.getFile2 = function () {
console.log($scope.fileUploadFile2[chIndex][sIndex]);
if ($scope.fileUploadFile2[chIndex][sIndex]) {
fileReaderFactory.readAsDataURL($scope.fileUploadFile2[chIndex][sIndex], $scope)
.then(function (result) {
$scope.chapters[chIndex].Sections[sIndex].sectionImgPreview = result;
});
}
};
and here is the html to preview the image:
<img ng-if="s.sectionImgPreview" class="img-responsive" ng-src="{{s.sectionImgPreview}}" alt="" onerror="this.src='#Url.Content("~/Content/Images/ToyApp.png")';" />
At this point, $scope.fileUploadFile2[chIndex][sIndex] is ready to post to the back end, which, in my case, is a C# Controller that accept the entire JSON containing Course Chapters and sections, image binaries and videos, text and html, into a complex class that will in turn store the information into the database schema.

Javascript: onload event not reaching for javascript's FileReader API

I need to create extract the signature of a file at the client level itself so as to positively determine its file type. Below is my file input object:
<input id="test1" type="file">
I wrote the following javascript code against it:
var fileInput = document.getElementById('test1');
fileInput.addEventListener('change', function(e) {
console.log("file selected");
var reader = new FileReader();
reader.onload = function(e) {
console.log("loaded");
var file_slice = gcUploadFile.slice(0,4);
console.log(file_slice);
var arr_buffer = reader.readAsArrayBuffer(file_slice);
console.log(arr_buffer);
}
});
Check out the fiddle for the above.
The trouble I am having is that my code does not even enters the onload fucntion.
What am i doing wrong?
Note: I am coding only using plain javascript but i am open to use Google Closure.
Why would it reach the onload handler, nothing is ever read by the FileReader.
You have to pass the file to the fileReader by reading it as something
var fileInput = document.getElementById('test1');
fileInput.addEventListener('change', function(e) {
console.log("file selected");
var reader = new FileReader();
reader.onload = function(e) {
console.log("loaded");
var file_slice = gcUploadFile.slice(0,4);
console.log(file_slice);
var arr_buffer = reader.readAsArrayBuffer(file_slice);
console.log(arr_buffer);
}
reader.readAsBinaryString(e.target.files[0]);
});

Reloading a file using html input

I have a textarea that can, quite obviously, be edited using keyboard entry. I also want to be able to load a file using an html input. I have done so, using the onchange event. (jsfiddle code linked below).
Suppose I load a file using the file loader - which works correctly in the example.
Then, I edit this file. Realising that the changes I have made are not desired, I want to reload this file. However, when using the html input, nothing changes since the selected file remains the same (the onchange event is not triggered). Is there a way to reload a file using an html input. (The only workaround I have found is to load a different file, then reload the original file ... which is not very elegant).
http://jsfiddle.net/aroberge/8PZyK/1/
var load_file = function() {
$("#fileInput").show();
var fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function(e) {
var file = fileInput.files[0];
var reader = new FileReader();
reader.onload = function(e) {
$("#editor").text(reader.result);
$("#fileInput").hide();
};
reader.readAsText(file);
});
};
$("#load").on("click", function(evt) {
load_file();
});
You could clear out the fileInput value after you've read the file from it:
updated fiddle:
http://jsfiddle.net/8PZyK/8/
var load_file = function() {
$("#fileInput").show();
var fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function(e) {
if (fileInput.files && fileInput.files.length > 0) {
var file = fileInput.files[0];
var reader = new FileReader();
fileInput.value = "";
reader.onload = function(e) {
$("#editor").val(reader.result);
$("#fileInput").hide();
}
};
reader.readAsText(file);
});
};
$("#load").on("click", function(evt) {
load_file();
});
After the file input has changed, and you grab out the data, simple reset the input field like so:
fileInput.value = ""; // Or with jQuery, $('input[file]').val('')
This will trigger another change (which you'll want to ignore), but will allow the user to select the same file again and still give you a change event.

Categories