Angular - (File) input works irregular on file select - html

Angular v 9.0.7
i have this input in my html which is gets triggered by the button:
<input #file (change)="importFile($event)" accept="audio/*, image/*, video/*" hidden type="file">
<button class="msg-npt-btn msg-npt-fl-icon" (click)="file.click()"></button>
it works for the first time i select a file but after that importFile() get called every second or third time if i select another file.
importFile(event) {
alert("import"); //test
if (event.target.files.length == 0) {
console.log("No file selected!");
return
}
this.selectedFile = event.target.files[0];
...

This is example how to load images may will it help.
importFile(event): void {
alert('import'); // test
const reader = new FileReader();
if (event.target.files.length === 0) {
console.log('No file selected!');
return;
}
reader.readAsDataURL(event.target.files[0]);
reader.onload = ((r) => {
this.selectedFile = r.target.result;
});
}

Related

How to load file after being uploaded (not saved in database yet) in angular, html

I have a file upload control in my angular app where user could upload any type of file except a few ones .exe, .sql etc
<input type="file" id="file" #file (change)="fileUploadHandler($event)" multiple>
fileupload.component.ts
fileUploadHandler(event: Event) {
const inputElement = event.target as HTMLInputElement;
if (inputElement.files && inputElement.files?.length) {
_each(inputElement.files, (_file) => {
const fileSize = _file.size;
if (fileSize < this.MAX_DOC_SIZE) {
const fileName = _file.name?.trim();
const doc = new Document();
doc.name = fileName;
doc.extension = fileName.slice(fileName.lastIndexOf('.') + 1);
doc.size = fileSize;
this.docs.push(doc);
}
});
}}
This list the files in UI as below
Now what I need is that when user click on a file, that file should open in a new tab
how can I do this?
On googling I see suggestions to use FileReader & gave a try
_each(inputElement.files, (_file) => {
const reader = new FileReader();
const data = reader.readAsDataURL(_file);
console.log(data) // nothing is printed on console
Please suggest. Thanks!
You have to enhance the code a little bit (as #mav-raj also stated). In Angular you can use the following:
_each(inputElement.files, (_file) => {
const reader = new FileReader();
reader.onloadend = ((result) => {
console.log(result) // now something will be printed!
});
reader.readAsDataURL(_file);
})

File preview showing last selected file in Angular 9

I am trying to preview selected file in Angular 9.
<h3>Angular 9 Image Preview before Upload:</h3>
<input #file type="file" accept='image/*' (change)="preview(file.files)" />
<img [src]="imgURL" height="200" *ngIf="imgURL">
And ts file is
preview(files) {
if (files.length === 0)
return;
var mimeType = files[0].type;
if (mimeType.match(/image\/*/) == null) {
let message = "Only images are supported.";
return;
}
var reader = new FileReader();
reader.readAsDataURL(files[0]);
reader.onload = (_event) => {
this.imgURL = _event.target.result;
}
}
But when first time i select the file i dont get any display, next time when i upload a file i get the display of last file i selected. I saw many working example with the same concept on internet, Is there any change in file upload login for new angular version i.e Angular 9.
After some RnD got the solution. We need to call detectChanges() after the imgUrl is changed.
preview(files) {
if (files.length === 0)
return;
var mimeType = files[0].type;
if (mimeType.match(/image\/*/) == null) {
let message = "Only images are supported.";
return;
}
var reader = new FileReader();
reader.readAsDataURL(files[0]);
reader.onload = (_event) => {
this.imgURL = _event.target.result;
this.ref.detectChanges();
}
}
the above solution worked fine for me.

angular2 filereader mysteriously fails

I'm using the setup shown below to read image file in angular2. I'm using input element to show the window to choose file and then trigger the addThumbnail function when the file is chosen. The click on the input is being triggered by another button. I noticed that the trigger of addThumbnail function sometimes fails silently i.e. the function is not even triggered after choosing a file. This happens may be 1 out of 5 times I'm not sure if this could happen because of the size of the file. I tried to debug this by setting a breakpoint inside addThumbnail function but that is not even being triggered.
<div class="extra-image-container">
<input type="file" accept="image/*" (change)="addThumbnail($event)" style="display:none;" #fileInput2/>
<div class="thumbnail-button" (click)="fileInput2.click()">
<span><i class="material-icons">photo_camera</i></span><br>
<span>Extra Images</span>
</div>
</div>
This is the addThumbnail function and the file reader function I'm using.
addThumbnail(event) {
console.log('adding thumbnail');
var subscription = this.readImage(event.target).subscribe((result) => {
this.thumbnails.push(result.imageUrl);
this.editedThumbnails.push(result.imageUrl);
subscription.unsubscribe()
});
}
readImage(inputValue: any) : Observable<any> {
var file:File = inputValue.files[0];
var myReader:FileReader = new FileReader();
var observable = new Observable(observer => {
myReader.onloadend = (e) => {
observer.next({imageUrl: myReader.result});
console.log("image loaded");
// var image = new Image();
// image.addEventListener("load", () => {
// observer.next({
// imageWidth: image.width,
// imageHeight: image.height,
// imageSize: file.size/1000,
// imageUrl: myReader.result
// })
// console.log("image loaded");
// })
// image.src = myReader.result;
}
myReader.readAsDataURL(file);//triggers the callback
})
return observable
}
It turns out that if you read same file one after another, then the change is not triggered because the files are same. So, to fix this all I had to do was set the value of input element to empty string after a file is loaded.
#ViewChild('fileInput2') private thumbImageInput: ElementRef;
// and in the addThumbnail method:
addThumbnail(event) {
var subscription = this.readImage2(event.target).subscribe((result) => {
this.thumbnails.push(result.imageUrl);
this.editedThumbnails.push(result.imageUrl);
window.URL.revokeObjectURL(result.imageUrl);
this.thumbImageInput.nativeElement.value = '';
});
}

Change other file inside EventStream of other gulp

I have one interesting question. Is it possible to change some file inside open stream (EventStream) inside gulp?
I have that stuff. I want to read some file inside opened stream and write that stuff to other file. How I can do it? Thanks.
gulp.task('handleGlobalStorage', function () {
return gulp.src('./global_storage.js')
.pipe(setEnvHostAndProxy())
.pipe(gulp.dest('./built'));
});
function setEnvHostAndProxy() {
return es.map(function(file, cb) {
var fileContent = file.contents.toString();
//some changes inside content
// if (!gutil.env.dev) return;
/* I have stuff that fetched from file and I modify it that I send it
down to pipe. But also I want to insert this stuff inside other
file. How I can do it? Should I create WritableStream of that file
and merge it ?*/
file.contents = new Buffer(fileContent);
// send the updated file down the pipe
cb(null, file);
});
}
I resolved that issue, here is solution (I will not show all code, only general). The main concept is - open file and write new stuff inside pipe :) that's all.
function setEnvHostAndProxy() {
var bsConfigFileContent = fs.readFileSync('./bs-config.js', 'utf8'),
bsConfigProxyPattern = /(proxyUrl\s?=\s?)["|'](.*)["|']/;
return es.map(function (file, cb) {
var fileContent = file.contents.toString(),
prodHost = fileContent.match(generateRegExpForHosts('prodHost'))[1],
prodProxy = fileContent.match(generateRegExpForHosts('prodProxy'))[1],
devProxy = fileContent.match(generateRegExpForHosts('devProxy'))[1],
devHost = fileContent.match(generateRegExpForHosts('devHost'))[1],
changedBsConfigFileStream,
res;
if (!gutil.env.dev) {
res = prodHandler();
changedBsConfigFileStream = bsConfigHandler(prodHost);
} else {
res = devHandler();
changedBsConfigFileStream = bsConfigHandler(devProxy);
}
fs.writeFile('./bs-config.js', changedBsConfigFileStream, 'utf8', function (err) {
if (err) throw (err);
});
file.contents = new Buffer(res);
cb(null, file);
} });

upload image from local into tinyMCE

tinyMCE has an insert image button, but how to handle its functionality
pls give some code
I have upvoted the code written by #pavanastechie, but I ended up rewriting it quite a lot. Here's a version that is far shorter, which might have value to some people
tinymce.init({
toolbar : "imageupload",
setup: function(editor) {
var inp = $('<input id="tinymce-uploader" type="file" name="pic" accept="image/*" style="display:none">');
$(editor.getElement()).parent().append(inp);
inp.on("change",function(){
var input = inp.get(0);
var file = input.files[0];
var fr = new FileReader();
fr.onload = function() {
var img = new Image();
img.src = fr.result;
editor.insertContent('<img src="'+img.src+'"/>');
inp.val('');
}
fr.readAsDataURL(file);
});
editor.addButton( 'imageupload', {
text:"IMAGE",
icon: false,
onclick: function(e) {
inp.trigger('click');
}
});
}
});
NOTE: this relies on jquery, and won't work without it. Also, it assumes that the browser supports window.FileReader, and doesn't check for it.
I used pavanastechie's and Chris Lear's solutions, which worked perfectly for me, and wanted to share a complete example built on theirs that uploads the image to the server and embeds the image using the URL provided back by the server:
tinymce.init({
toolbar: 'imageupload',
setup: function(editor) {
initImageUpload(editor);
}
});
function initImageUpload(editor) {
// create input and insert in the DOM
var inp = $('<input id="tinymce-uploader" type="file" name="pic" accept="image/*" style="display:none">');
$(editor.getElement()).parent().append(inp);
// add the image upload button to the editor toolbar
editor.addButton('imageupload', {
text: '',
icon: 'image',
onclick: function(e) { // when toolbar button is clicked, open file select modal
inp.trigger('click');
}
});
// when a file is selected, upload it to the server
inp.on("change", function(e){
uploadFile($(this), editor);
});
}
function uploadFile(inp, editor) {
var input = inp.get(0);
var data = new FormData();
data.append('image[file]', input.files[0]);
$.ajax({
url: '/admin/images',
type: 'POST',
data: data,
processData: false, // Don't process the files
contentType: false, // Set content type to false as jQuery will tell the server its a query string request
success: function(data, textStatus, jqXHR) {
editor.insertContent('<img class="content-img" src="' + data.url + '"/>');
},
error: function(jqXHR, textStatus, errorThrown) {
if(jqXHR.responseText) {
errors = JSON.parse(jqXHR.responseText).errors
alert('Error uploading image: ' + errors.join(", ") + '. Make sure the file is an image and has extension jpg/jpeg/png.');
}
}
});
}
!!!!ENJOY!!! here is the solution to load directly from local computer
JSFIDDLE DEMO
<textarea name="content"></textarea>
<title>Local image loading in to tinymce</title>
<br/>
<b>Image size should be lessthan 500kb</b>
JAVA SCRIPT CODE
`
tinymce.init({
selector: "textarea",
toolbar: "mybutton",
setup: function(editor) {
editor.addButton('mybutton', {
text:"IMAGE",
icon: false,
onclick: function(e) {
console.log($(e.target));
if($(e.target).prop("tagName") == 'BUTTON'){
console.log($(e.target).parent().parent().find('input').attr('id'));
if($(e.target).parent().parent().find('input').attr('id') != 'tinymce-uploader') {
$(e.target).parent().parent().append('<input id="tinymce-uploader" type="file" name="pic" accept="image/*" style="display:none">');
}
$('#tinymce-uploader').trigger('click');
$('#tinymce-uploader').change(function(){
var input, file, fr, img;
if (typeof window.FileReader !== 'function') {
write("The file API isn't supported on this browser yet.");
return;
}
input = document.getElementById('tinymce-uploader');
if (!input) {
write("Um, couldn't find the imgfile element.");
} else if (!input.files) {
write("This browser doesn't seem to support the `files` property of file inputs.");
} else if (!input.files[0]) {
write("Please select a file before clicking 'Load'");
} else {
file = input.files[0];
fr = new FileReader();
fr.onload = createImage;
fr.readAsDataURL(file);
}
function createImage() {
img = new Image();
img.src = fr.result;
editor.insertContent('<img src="'+img.src+'"/>');
}
});
}
if($(e.target).prop("tagName") == 'DIV'){
if($(e.target).parent().find('input').attr('id') != 'tinymce-uploader') {
console.log($(e.target).parent().find('input').attr('id'));
$(e.target).parent().append('<input id="tinymce-uploader" type="file" name="pic" accept="image/*" style="display:none">');
}
$('#tinymce-uploader').trigger('click');
$('#tinymce-uploader').change(function(){
var input, file, fr, img;
if (typeof window.FileReader !== 'function') {
write("The file API isn't supported on this browser yet.");
return;
}
input = document.getElementById('tinymce-uploader');
if (!input) {
write("Um, couldn't find the imgfile element.");
} else if (!input.files) {
write("This browser doesn't seem to support the `files` property of file inputs.");
} else if (!input.files[0]) {
write("Please select a file before clicking 'Load'");
} else {
file = input.files[0];
fr = new FileReader();
fr.onload = createImage;
fr.readAsDataURL(file);
}
function createImage() {
img = new Image();
img.src = fr.result;
editor.insertContent('<img src="'+img.src+'"/>');
}
});
}
if($(e.target).prop("tagName") == 'I'){
console.log($(e.target).parent().parent().parent().find('input').attr('id')); if($(e.target).parent().parent().parent().find('input').attr('id') != 'tinymce-uploader') { $(e.target).parent().parent().parent().append('<input id="tinymce-uploader" type="file" name="pic" accept="image/*" style="display:none">');
}
$('#tinymce-uploader').trigger('click');
$('#tinymce-uploader').change(function(){
var input, file, fr, img;
if (typeof window.FileReader !== 'function') {
write("The file API isn't supported on this browser yet.");
return;
}
input = document.getElementById('tinymce-uploader');
if (!input) {
write("Um, couldn't find the imgfile element.");
} else if (!input.files) {
write("This browser doesn't seem to support the `files` property of file inputs.");
} else if (!input.files[0]) {
write("Please select a file before clicking 'Load'");
} else {
file = input.files[0];
fr = new FileReader();
fr.onload = createImage;
fr.readAsDataURL(file);
}
function createImage() {
img = new Image();
img.src = fr.result;
editor.insertContent('<img src="'+img.src+'"/>');
}
});
}
}
});
}
});
`
Din't try iManager but found tinyFCK good and easy to configure which gives CKEditor's filemanager integrated with TinyMCE
1.Download TinyFCK
2.replace filemanger folder in tinyFCK with filemanager folder of ur CKEditor
3.code :
-
tinyMCE.init({
theme : "advanced",
file_browser_callback : "fileBrowserCallBack",
});
function fileBrowserCallBack(field_name, url, type, win) {
var connector = "../../filemanager/browser.html?Connector=connectors/php/connector.php";
var enableAutoTypeSelection = true;
var cType;
tinyfck_field = field_name;
tinyfck = win;
switch (type) {
case "image":
cType = "Image";
break;
case "flash":
cType = "Flash";
break;
case "file":
cType = "File";
break;
}
if (enableAutoTypeSelection && cType) {
connector += "?Type=" + cType;
}
window.open(connector, "tinyfck", "modal,width=600,height=400");
}
I know this post is old, but maybe this will help someone trying to find a open source file manager for tinymce:
https://github.com/2b3ez/FileManager4TinyMCE
This worked great for me.
Based on #Chris Lear's answer, I have re-modified the script so that it supports multiple file uploads to server, and removed the data image for preview after content is posted and before table is updated with a little php script
tinymce.init({
selector: 'textarea',
setup: function(editor) {
var n = 0;
var form = $('#form_id'); // your form id
editor.addButton( 'imageupload', {
text:"IMAGE",
icon: false,
onclick: function(e) {
$(form).append('<input id="tinymce-uploader_'+n+'" class="tinymce-uploader" type="file" name="pic['+n+']" mutliple accept="image/*" style="display: none;">');
$('#tinymce-uploader_'+n).trigger('click');
n++;
$('.tinymce-uploader').on("change",function(){
var input = $(this).get(0);
var file = input.files[0];
var filename = file.name;
var fr = new FileReader();
fr.onload = function() {
var img = new Image();
img.src = fr.result;
editor.insertContent('<img data-name="'+filename+'" src="'+img.src+'"/>');
}
fr.readAsDataURL(file);
});
}
});
},
And on php side inside the upload php file:
function data2src($content, $img_path ='') {
preg_match('/data\-name="([^"]+)/i',$content, $data_name);
$tmp = preg_replace('/src=["]data([^"]+)["]/i', '', $content);
$content = preg_replace('/data\-name\=\"/i', 'src="'.$img_path, $tmp);
return $content;
}
I know it is an old question. However, I think this answer may help somebody who wants to upload multiple images by using tinyMCE 5.xx.
Based on #Chris Lear's and #stephen.hanson's answer, I modify some code to support multiple images uploading. Here is my code. Hope it could help somebody.
tinymce.init({
toolbar: 'imageupload',
setup: function(editor) {
initImageUpload(editor);
}
});
function initImageUpload(editor) {
// create input and insert in the DOM
var inp = $(`<input id='tinymce-uploader' type='file' name='pic' accept='image/*' style='display:none' multiple>`);
$(editor.getElement()).parent().append(inp);
// add the image upload button to the editor toolbar
editor.addButton('imageupload', {
text:'IMAGE',
onAction: function(_) {
// when toolbar button is clicked, open file select modal
inp.trigger('click');
}
});
// when a file is selected, upload it to the server
inp.on('change',function(){
for(let i=0;i<inp[0].files.length;i++){
let file = inp[0].files[i];
let data = new FormData();
data.append('multipartFile',file);
axios.post('/upload/image/url',
data,
{
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(res => {
if (res.status = 200) {
editor.insertContent('<img class="content-img" src="' + data.url + '"/>');
// clear data to avoid uploading same data not working in the second time
inp.val('');
}
})
}
It works for image upload.Is this possible for file upload ? I want to add a custom file upload option from local into tinyMCE and want to show it by url .
Code is something like below which not working:
ed.addButton('mybutton2', {
text:"File",
icon: false,
onclick: function(e) {
console.log($(e.target));
if($(e.target).prop("tagName") == 'BUTTON'){
console.log($(e.target).parent().parent().find('input').attr('id'));
if($(e.target).parent().parent().find('input').attr('id') !=
'tinymce-uploader') {
$(e.target).parent().parent().append('<input id="tinymce-
uploader" type="file" name="pic" accept="*" height="100" weidth="100"
style="display:none">');
}
$('#tinymce-uploader').trigger('click');
$('#tinymce-uploader').change(function(){
var input, file, fr, img;
if (typeof window.FileReader !== 'function') {
write("The file API isn't supported on this browser yet.");
return;
}
input = document.getElementById('tinymce-uploader');
// var URL = document.my_form.my_field.value;
alert(input.files[0]);
if (!input) {
write("Um, couldn't find the imgfile element.");
} else if (!input.files) {
write("This browser doesn't seem to support the `files`
property of file inputs.");
} else if (!input.files[0]) {
write("Please select a file before clicking 'Load'");
alert( input.files[0]);
} else {
file = input.files[0];
fr = new FileReader();
fr.onload = createFile;
fr.readAsDataURL(file);
// alert(fr.result);
}
function createFile() {
//what should I write here?
ed.insertContent('<a href="'+img.src+'">download
file_name</a>');
}
});
}
}
});