Image upload for multiple fields Angular 5 - angular5

I have a scenario where i have to create multiple file upload fields dynamically using reactive forms with form array and upload multiple image for that particular field in angular 5 or angular reactive forms and the image needs to be displayed parallel to that form field name .
Please help with me with any sample code in stack blitz or from any links. Also
thanks.

You can do the file upload part using formData.
const formData: FormData = new FormData();
formData.append('file1', file1, file1.name);
formData.append('file2', file2, file2);
this.http.post(url, formData);
And using the change event in the
<input type="file" (chnage)="onChange($event)"> you can get the image source of the file you select.
Here
public fileList: FileList;
public imageUrls: any[];
public files: any[];
public onChange(event) {
if (event.target.files.length === 0) {
return;
}
this.fileList = event.target.files;
for (let i = 0; i < this.fileList.length; i++) {
const file = this.fileList[i];
if (!file.type.match('image')) {
continue;
}
this.files.push(file);
const picReader = new FileReader();
picReader.onload = (e: any) => {
const picFile = e.target;
this.imageUrls.push(picFile.result);
};
picReader.readAsDataURL(file);
}
}
And in the template
<input type="file"
(change)="onChange($event)"
placeholder="Upload file"
accept="image/*" multiple>
<p>(You may choose more than one file to upload.)</p>
<ng-container *ngFor="let item of imageUrls; let i = index">
<img [src]="item" height="100" class="img-thumbnail">
</ng-container>
This is just a idea. Just give it a try.

Related

Cancel a previous axios request on new request in Vue Js

I am trying to implement a search which loads user data from the backend on every word change using #input and populate in datalist, now for every change a new request is generated while the old request is still processing/pending this causes some problems. I am looking to cancel old request on every new request that will take place.
Html code in vue js
<input type="text" class="form-control" placeholder="Search Name" v-model="forms.name" list="getname" #input="inputData()" required> <datalist id="getInput" > <option v-for="option in options">{{option}}</option> </datalist>
Function to load data
axios.get('Url/GetUser/'+ this.forms.name).then((response) => {if(response.data.error){ this.errorNya = response.data; this.loading2 = false;}else{ this.errorNya.username = ""; this.options = response.data; this.loading2= false; this.disableButton = true; }
I have referred the documentation and other sources for this question, and i found a solution which suited me best.
this.cancelFunc();
//Below line creates a cancel token for this request
let axiosSource = axios.CancelToken.source();
this.request = { cancel: axiosSource.cancel };
//then we pass the token to the request we want to cancel.
axios.get('/Url/GetUser/'+ this.forms.username, {cancelToken: axiosSource.token,}).then((response) => {
if (response.data.error) {
this.errorNya = response.data;
this.loading2 = false;
} else {
this.errorNya.username = "";
this.options = response.data;
this.loading2 = false;
this.disableButton = true;
}
},
cancelFunc() {
if (this.request)
this.request.cancel();
},
i know this will not be the best way to do this, but this solved my problem.

How in bootstrap-vue convert FileReader to blob and upload to server?

In #vue/cli 4.1.1 app I use bootstrap-vue and b-form-file conponent for images uploading
https://bootstrap-vue.js.org/docs/components/form-file/#multiple-files
with definition :
<b-form-file
id="upload_ad_image"
v-model="new_upload_ad_image"
:state="Boolean(new_upload_ad_image)"
placeholder="Choose a file or drop it here..."
drop-placeholder="Drop file here..."
accept="image/jpeg, image/png, image/gif"
></b-form-file>
<div ref="uploaded_img_preview" id="uploaded_img_preview" class="m-2" >Uploaded image preview :</div>
I found snippet https://codepen.io/Tenderfeel/pen/rgqWXR
and using it I show selected file on my form for preview.
Next I need to upload it on the server. I have an expierence of uploading image as blog using code like :
fetch(this.taskRow.imageFile.blob).then(function (response) {
if (response.ok) {
return response.blob().then(function (imageBlob) {
let imageUploadData = new FormData()
imageUploadData.append('id', self.taskRow.id)
imageUploadData.append('image', imageBlob)
imageUploadData.append('image_filename', self.taskRow.imageFile.name)
But I need to convert uploading image to blob. I use method when image is selected:
But got error : Error in callback for watcher "new_upload_ad_image": "InvalidStateError: Failed to execute 'readAsDataURL' on 'FileReader': The object is already busy reading Blobs
watch: {
new_upload_ad_image(val) {
if (!val) return;
if (this.previewImg) {
this.previewImg.remove();
}
const img = document.createElement("img");
img.classList.add("obj");
img.file = this.new_upload_ad_image;
console.log('img.file::')
console.log(img.file)
this.previewImg = img;
console.log('this.$refs.uploaded_img_preview::')
console.log(this.$refs.uploaded_img_preview)
console.log('img::')
console.log(img)
this.$refs.uploaded_img_preview.appendChild(img);
const fileReader = new FileReader();
fileReader.onload = (e) => {
this.previewImg.src = e.target.result;
};
fileReader.readAsDataURL(this.new_upload_ad_image);
console.log('fileReader::')
console.log(fileReader)
let blobObj= fileReader.readAsDataURL(img.file) // RAISE ERROR :
console.log('blobObj::')
console.log(blobObj)
}
},
What I see in the console : https://imgur.com/a/2EZxq9C
How to get blob and upload it on server?
MODIFIED BLOCK :
having file input with id="upload_ad_image" defined :
<b-form-file
id="upload_ad_image"
v-model="new_upload_ad_image"
:state="Boolean(new_upload_ad_image)"
placeholder="Choose a file or drop it here..."
drop-placeholder="Drop file here..."
accept="image/jpeg, image/png, image/gif"
></b-form-file>
I run fetch and see that image blob is invalid and file is created, but it is invalid
I have :
var self = this
const upload_ad_image = document.getElementById('upload_ad_image')
console.log('upload_ad_image::')
console.log(upload_ad_image)
console.log('upload_ad_image.files::')
console.log(upload_ad_image.files[0])
if (typeof upload_ad_image.files[0] == 'undefined') {
self.showPopupMessage('Ad image upload', 'Invalid image !', 'warn')
return
}
fetch(upload_ad_image.files[0].blob).then(function (response) {
if (response.ok) {
return response.blob().then(function (imageBlob) {
console.log('imageBlob::')
console.log(imageBlob) // Looks like this var has invalid content(printscreen below)!
let imageUploadData = new FormData()
imageUploadData.append('ad_id', self.editableAd.id)
imageUploadData.append('main', self.new_upload_ad_image_main)
imageUploadData.append('info', self.new_upload_ad_image_info)
imageUploadData.append('image', imageBlob)
imageUploadData.append('image_filename', upload_ad_image.files[0].name)
I see in console : https://imgur.com/a/4ees55C
What is wrong and how it can be fixed ?
"bootstrap-vue": "^2.3.0",
"vue": "^2.6.11",
Thanks!
File objects do inherit from the Blob interface.
All you can do with a Blob, you can also do it with a File, so in your code you can directly append this.new_upload_ad_image to your FormData.
const inp = document.getElementById('inp');
inp.onchange = (evt) => {
const formData = new FormData();
formData.append( 'my-file', inp.files[0], 'file.ext' );
// check it's correctly in the FormData
console.log( [...formData.entries()] );
};
<input type="file" id="inp">

How to preview files before uploaded to server by using file-upload component of vue.js & element-ui?

I'm using vue.js & element-ui to upload files and preview files. I want to preview file(.pdf/.docx/.jpg...) before uploaded to server.
<el-upload
ref="uploadFile"
:on-change="onUploadChange"
:on-preview="handlePreview"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:file-list="fileList"
:http-request="handleUpload"
:data="extendData"
:auto-upload="false"
class="upload-demo"
drag
action="uploadUrl"
multiple>
<i class="el-icon-upload"/>
<div class="el-upload__text">drag here, or <em>click to upload</em></div>
</el-upload>
Only the on-change function can get the content of the file, while the on-preview function only get the meta message. How to get the file content and preview that before which is uploaded to server?
It's not the meta, it's the file. So you need to use a FileReader on the file:
handlePreview(file) {
const reader = new FileReader()
reader.onload = e => console.log(e.target.result) // here is the result you can work with.
reader.readAsText(file)
}
I am also using Element-UI upload box, the following code allow user to import a JSON file to Vue, and preview its content in a new window when clicking the file name. The file is read and stored as object in data during on-change, then
Vue component:
<el-upload class="upload-box" drag action="" :auto-upload="false" :on-change="handleImport" :on-preview="handlePreview" :limit="1" :on-exceed="handleExceed">
<i class="el-icon-upload"></i>
<div class="el-upload__text">Drop file here or <em>click to upload</em></div>
<div class="el-upload__tip" slot="tip">Single JSON file with size less than 500kb</div>
</el-upload>
Script:
export default {
data() {
return {
uploadFile: null,
fileContent: null,
}
},
methods: {
handleImport(file) {
this.uploadFile = file
let reader = new FileReader()
reader.readAsText(this.uploadFile.raw)
reader.onload = async (e) => {
try {
this.fileContent = JSON.parse(e.target.result)
} catch (err) {
console.log(`Load JSON file error: ${err.message}`)
}
}
},
handlePreview() {
let myWindow = window.open();
myWindow.document.write(JSON.stringify(this.fileContent));
myWindow.document.close();
},
handleExceed(files, fileList) {
this.$message.warning(`The limit is 1, you selected ${files.length + fileList.length} totally, please first remove the unwanted file`);
},
},
}

SimpleCart.js search functionality

Have been using simpleCart for a while and it works great and i know it has a search function in it but it only seems to search certain elements my question is this, i would like to know if it can be set up to search within the contents of html files? as all the items are stored in Html pages for simple cataloging.
try this: JS
function filter(e){
search = e.value.toLowerCase();
console.log(e.value)
document.querySelectorAll('.item_name').forEach(function(row){
text = row.innerText.toLowerCase();
if(text.match(search)){
row.style.display="block"
} else {
row.style.display="none"
}
// need to count hidden items and if all instances of .kb-items are hidden, then hide .kb-item
var countHidden = document.querySelectorAll(".item_name[style='display: none;']").length;
console.log(countHidden);
})
}
function detectParent()
{
var collectionref=document.querySelectorAll(".simpleCart_shelfItem");
collectionref.forEach(group=>{
var itemcollection=group.getElementsByClassName("item_name");
var hidecounter=0;
for(var j=0;j<itemcollection.length;j++)
{
if(itemcollection[j].style.display==='none')
{
hidecounter++;
}
}
if(hidecounter===itemcollection.length)
{
group.style.display="none";
}else{
group.style.display="block";
}
});
}
And HTML:
<input type="text" onkeyup="filter(this);detectParent();"/>

How to get uploaded image in serverside using Ember.js

I'm new to Ember.js and I'm stuck with a problem I need to save the uploaded image in db but I dont know how to do that I wrote code for upload the image but i'm stuck with passing it to the server my current code is given below
App.js
App = Ember.Application.create();
App.PreviewImageView = Ember.View.extend({
attributeBindings: ['name', 'width', 'height', 'src'],
tagName: 'img',
viewName: 'previewImageView',
printme: function () {
console.log('in previewImageView');
}
});
App.FileField= Ember.TextField.extend({
type: 'file',
attributeBindings: ['name'],
change: function (evt) {
var input = evt.target;
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
this.$().parent(':eq(0)').children('img:eq(0)').attr('src', e.target.result);
var view = that.getPath('parentView.previewImageView');
view.set('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
});
html
<script type="text/x-handlebars">
{{view App.FileField name="logo_image" contentBinding="content"}}
{{view App.PreviewImageView width="200" height="100" }}
</script>
I think you can mix some traditional MVC methods to solve your problem. from your current code I can assume that showing a preview of the image is completed so to get that file in server side just use the following code in your html
#using (Html.BeginForm("FileUpload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" {{view Wizard.FileField contentBinding="content"}} />
<input type="submit" id="btnUpload" value="Upload" />
}
and In you controller method you can access the file like this
public ActionResult FileUpload(HttpPostedFileBase file)
{
// Do what you want
}
To save the image in db you have to convert it into bytes (sql server 2008 support image now but db like postgresql still need image as bytes) to do that use the following method
MemoryStream target = new MemoryStream();
file.InputStream.CopyTo(target);
byte[] bytes= target.ToArray();
return View();
Assuming you are using ember-data, you can create a model to represent the image and then create/save from the reader's onload callback. For example:
App.LogoImage = DS.Model.extend({
id: DS.attr('number'),
attachment: DS.attr('string')
});
//in App.FileField...
reader.onload = function (e) {
this.$().parent(':eq(0)').children('img:eq(0)').attr('src', e.target.result);
var view = that.getPath('parentView.previewImageView');
view.set('src', e.target.result);
var file = e.srcElement.result;
var logo = App.LogoImage.createRecord({ attachment: file });
logo.save();
}