Skip to content

Commit 9800c34

Browse files
authored
Committed the example project.
1 parent 7128577 commit 9800c34

File tree

10 files changed

+397
-2
lines changed

10 files changed

+397
-2
lines changed

README.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,14 @@
1-
# How-to-Preview-Uploaded-Files-with-Vue-File-Upload-and-an-Image-Element
2-
A quick-start Vue project that shows how to display a preview of uploaded image files in the Syncfusion Vue File Upload component. This project contains code to customize the file drop area and file list to show the image preview using an image element. It also contains code to create custom upload and remove buttons for handling images.
1+
# How to Preview Uploaded Files with Vue File Upload and an Image Element
2+
3+
A quick-start Vue project that shows how to display a preview of uploaded image files in the Syncfusion [Vue File Upload](https://www.syncfusion.com/vue-components/vue-file-upload?utm_source=github&utm_medium=listing&utm_campaign=tutorial-videos-vue-file-upload-preview-uploaded-files-sample) component. This project contains code to customize the file drop area and file list to show the image preview using an image element. It also contains code to create custom upload and remove buttons for handling images.
4+
5+
Watch the video: Coming soon…
6+
7+
Refer to the following documentation to learn about the Vue File Upload component: https://ej2.syncfusion.com/vue/documentation/uploader/how-to/preview-images-before-uploading
8+
9+
Check out this online example of the Vue File Upload component: https://ej2.syncfusion.com/vue/demos/#/material3/uploader/image-preview.html
10+
11+
Before working on this project, make sure you have the latest versions of Node.js and Visual Studio Code on your machine.
12+
13+
## How to run this application
14+
To run this application, you need to clone the `How-to-Preview-Uploaded-Files-with-Vue-File-Upload-and-an-Image-Element` repository and open the application in Visual Studio Code. Then, you can install all the necessary Vue packages in your project using the `npm install` command and run your project using the `npm run dev` command.

index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Vite + Vue</title>
8+
</head>
9+
<body>
10+
<div id="app"></div>
11+
<script type="module" src="/src/main.js"></script>
12+
</body>
13+
</html>

package.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "myvueapp",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite",
8+
"build": "vite build",
9+
"preview": "vite preview"
10+
},
11+
"dependencies": {
12+
"@syncfusion/ej2-vue-buttons": "^26.1.40",
13+
"@syncfusion/ej2-vue-inputs": "^26.1.40",
14+
"vue": "^3.4.29"
15+
},
16+
"devDependencies": {
17+
"@vitejs/plugin-vue": "^5.0.5",
18+
"vite": "^5.3.3"
19+
}
20+
}

public/vite.svg

Lines changed: 1 addition & 0 deletions
Loading

src/App.vue

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
<template>
2+
<div class="container">
3+
<div id="dropArea" class="uploader-image-preview-drop-area">
4+
<span>
5+
Drop image (JPG, PNG) files here or <a href="#" id="browse"><u>Browse</u></a>
6+
</span>
7+
<ejs-uploader ref="uploaderObj" :asyncSettings="asyncSettings" :allowedExtensions="'.jpg, .png'"
8+
:dropArea="dropElement" cssClass="uploader-preview"
9+
:selected="onFileSelected"
10+
:success="onSuccess"
11+
></ejs-uploader>
12+
</div>
13+
</div>
14+
</template>
15+
16+
<script>
17+
import { UploaderComponent } from '@syncfusion/ej2-vue-inputs';
18+
import { createElement, isNullOrUndefined, detach } from '@syncfusion/ej2-base';
19+
20+
export default {
21+
components: {
22+
'ejs-uploader': UploaderComponent
23+
},
24+
data() {
25+
return {
26+
asyncSettings: {
27+
saveUrl: 'https://services.syncfusion.com/vue/production/api/FileUploader/Save',
28+
removeUrl: 'https://services.syncfusion.com/vue/production/api/FileUploader/Remove'
29+
},
30+
dropElement: '#dropArea',
31+
fileElements: [],
32+
filesDetails: []
33+
};
34+
},
35+
mounted() {
36+
document.getElementById('browse').onclick = function () {
37+
document.querySelector('.e-file-select-wrap').querySelector('button').click();
38+
return false;
39+
};
40+
},
41+
methods:{
42+
onFileSelected(selectedEvent){
43+
if(isNullOrUndefined(document.getElementById('dropArea').querySelector('.e-upload-files'))){
44+
document.getElementsByClassName('uploader-preview')[0].appendChild(createElement('ul',{className:'e-upload-files'}));
45+
}
46+
selectedEvent.filesData.forEach(file=>{
47+
this.formSelectedData(file);
48+
});
49+
this.filesDetails = [...this.filesDetails, ...selectedEvent.filesData];
50+
selectedEvent.cancel = true;
51+
},
52+
formSelectedData(file){
53+
let liEle = createElement('li', {className: 'e-upload-file-list', attrs: {'data-file-name': file.name }});
54+
let imageElement = createElement('img', { className: 'upload-image'});
55+
let wrapper = createElement('span');
56+
wrapper.appendChild(imageElement);
57+
liEle.appendChild(wrapper);
58+
liEle.appendChild(createElement('div', {className:'file-name', innerHTML: file.name }));
59+
liEle.appendChild(createElement('div', {className:'file-size', innerHTML:
60+
this.$refs.uploaderObj.bytesToSize(file.size)
61+
}));
62+
let uploadBtn = createElement('span', { id: 'iconUpload', className:
63+
'e-upload-icon e-icons e-file-remove-btn'
64+
});
65+
uploadBtn.addEventListener('click', this.uploadFile);
66+
liEle.appendChild(uploadBtn);
67+
68+
let removeBtn = createElement('span', { id: 'removeIcon', className:
69+
'e-icons e-file-remove-btn'
70+
});
71+
removeBtn.addEventListener('click', this.removeFile);
72+
liEle.appendChild(removeBtn);
73+
74+
let reader = new FileReader();
75+
reader.onload = () => {
76+
liEle.querySelector('.upload-image').src = reader.result;
77+
};
78+
reader.readAsDataURL(file.rawFile);
79+
80+
document.querySelector('.e-upload-files').appendChild(liEle);
81+
this.fileElements.push(liEle);
82+
},
83+
uploadFile(event){
84+
let fileIndex = this.fileElements.indexOf(event.currentTarget.parentElement);
85+
this.$refs.uploaderObj.upload([this.filesDetails[fileIndex]], true);
86+
},
87+
onSuccess(event){
88+
let li = document.querySelector(`[data-file-name="${event.file.name}"]`);
89+
if(event.operation === 'upload'){
90+
li.querySelector('#iconUpload').removeEventListener('click', this.uploadFile);
91+
li.querySelector('.file-name').style.color = '#4CAF50';
92+
li.querySelector('#removeIcon').classList.replace('e-file-remove-btn','e-file-delete-btn');
93+
}else if(event.operation === 'remove'){
94+
this.filesDetails.splice(this.fileElements.indexOf(li),1);
95+
this.fileElements.splice(this.fileElements.indexOf(li),1);
96+
detach(li);
97+
}
98+
},
99+
removeFile(event){
100+
let fileIndex = this.fileElements.indexOf(event.currentTarget.parentElement);
101+
let fileInfo = this.filesDetails[fileIndex];
102+
if(fileInfo.statusCode === '2'){
103+
this.$refs.uploaderObj.remove(fileInfo);
104+
this.$refs.uploaderObj.clearAll();
105+
}else if(fileInfo.statusCode === '1' || fileInfo.statusCode === '0'){
106+
this.filesDetails.splice(fileIndex,1);
107+
this.fileElements.splice(fileIndex,1);
108+
detach(event.currentTarget.parentElement);
109+
this.$refs.uploaderObj.clearAll();
110+
}
111+
}
112+
}
113+
};
114+
</script>
115+
116+
<style>
117+
@import "../node_modules/@syncfusion/ej2-base/styles/material.css";
118+
@import "../node_modules/@syncfusion/ej2-buttons/styles/material.css";
119+
@import "../node_modules/@syncfusion/ej2-vue-inputs/styles/material.css";
120+
121+
@font-face {
122+
font-family: 'Uploader_Icon';
123+
src:
124+
url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAAKAIAAAwAgT1MvMj1tSfIAAAEoAAAAVmNtYXDnEOdVAAABiAAAADZnbHlmoZcPvgAAAcgAAABAaGVhZBLQTSUAAADQAAAANmhoZWEINQQDAAAArAAAACRobXR4CAAAAAAAAYAAAAAIbG9jYQAgAAAAAAHAAAAABm1heHABDgAdAAABCAAAACBuYW1lQySinQAAAggAAAIxcG9zdLfl0usAAAQ8AAAAMgABAAAEAAAAAFwEAAAAAAAD2AABAAAAAAAAAAAAAAAAAAAAAgABAAAAAQAA2vKJUF8PPPUACwQAAAAAANftBBgAAAAA1+0EGAAAAAAD2AP4AAAACAACAAAAAAAAAAEAAAACABEAAgAAAAAAAgAAAAoACgAAAP8AAAAAAAAAAQQAAZAABQAAAokCzAAAAI8CiQLMAAAB6wAyAQgAAAIABQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUGZFZABA5wDnAAQAAAAAXAQAAAAAAAABAAAAAAAABAAAAAQAAAAAAAACAAAAAwAAABQAAwABAAAAFAAEACIAAAAEAAQAAQAA5wD//wAA5wD//wAAAAEABAAAAAEAAAAAAAAAIAAAAAIAAAAAA9gD+AAHABAAADchESMVITUjEzM3ETMRFzMBKAOwPvzMPp1mtUC1Zv7FCAF6vb0BO7X+EAHwtQE7AAAAABIA3gABAAAAAAAAAAEAAAABAAAAAAABAAgAAQABAAAAAAACAAcACQABAAAAAAADAAgAEAABAAAAAAAEAAgAGAABAAAAAAAFAAsAIAABAAAAAAAGAAgAKwABAAAAAAAKACwAMwABAAAAAAALABIAXwADAAEECQAAAAIAcQADAAEECQABABAAcwADAAEECQACAA4AgwADAAEECQADABAAkQADAAEECQAEABAAoQADAAEECQAFABYAsQADAAEECQAGABAAxwADAAEECQAKAFgA1wADAAEECQALACQBLyBVcGxvYWRlclJlZ3VsYXJVcGxvYWRlclVwbG9hZGVyVmVyc2lvbiAxLjBVcGxvYWRlckZvbnQgZ2VuZXJhdGVkIHVzaW5nIFN5bmNmdXNpb24gTWV0cm8gU3R1ZGlvd3d3LnN5bmNmdXNpb24uY29tACAAVQBwAGwAbwBhAGQAZQByAFIAZQBnAHUAbABhAHIAVQBwAGwAbwBhAGQAZQByAFUAcABsAG8AYQBkAGUAcgBWAGUAcgBzAGkAbwBuACAAMQAuADAAVQBwAGwAbwBhAGQAZQByAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAHUAcwBpAG4AZwAgAFMAeQBuAGMAZgB1AHMAaQBvAG4AIABNAGUAdAByAG8AIABTAHQAdQBkAGkAbwB3AHcAdwAuAHMAeQBuAGMAZgB1AHMAaQBvAG4ALgBjAG8AbQAAAAACAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAgEDAAhVcGxvYWRlcgAAAAA=) format('truetype');
125+
font-weight: normal;
126+
font-style: normal;
127+
}
128+
129+
.uploader-preview.e-upload .e-upload-files .e-icons.e-upload-icon {
130+
font-family: 'Uploader_Icon';
131+
font-size: 15px;
132+
left: 20px;
133+
}
134+
135+
.uploader-preview .e-upload-files .e-file-delete-btn.e-icons,
136+
.uploader-preview .e-upload-files .e-file-remove-btn.e-icons {
137+
top: 120px;
138+
background-color: rgb(246, 245, 245);
139+
border-radius: 50%;
140+
font-size: 12px;
141+
left: 80px;
142+
}
143+
144+
.uploader-preview .e-upload-files li .e-icons {
145+
visibility: hidden;
146+
}
147+
148+
.uploader-preview .e-upload-files li:hover .e-icons {
149+
visibility: visible;
150+
}
151+
152+
.uploader-preview.e-upload .e-upload-files .e-icons:not(.e-uploaded):hover {
153+
background-color: #e6e6e6;
154+
border-color: #adadad;
155+
color: #333;
156+
}
157+
158+
.uploader-preview.e-upload .e-upload-files .e-icons.e-upload-icon::before {
159+
content: '\e700';
160+
}
161+
162+
.uploader-preview .file-name {
163+
padding: 3px 10px;
164+
overflow: hidden;
165+
text-overflow: ellipsis;
166+
width: 90%;
167+
white-space: nowrap;
168+
}
169+
170+
.uploader-preview .file-size {
171+
padding: 0px 10px;
172+
}
173+
174+
.uploader-preview .upload-image{
175+
height: 150px;
176+
width: 150px;
177+
margin: 10px;
178+
}
179+
.container {
180+
position: absolute;
181+
top: 15%;
182+
left: 40%;
183+
max-width: 505px;
184+
margin: auto;
185+
}
186+
187+
.uploader-image-preview-drop-area {
188+
border: 1px dashed #c3c3cc;
189+
position: relative;
190+
text-align: center;
191+
padding: 20px 5px 18px 5px;
192+
}
193+
194+
.uploader-preview.e-upload .e-upload-files {
195+
text-align: initial;
196+
border-top: none;
197+
}
198+
199+
.uploader-preview .e-file-select-wrap {
200+
display: none;
201+
}
202+
203+
.e-upload {
204+
border: 0px;
205+
}
206+
207+
.e-upload .e-upload-files .e-upload-file-list {
208+
border: 0px;
209+
display: inline-block;
210+
width: 165px;
211+
}
212+
213+
</style>

src/assets/vue.svg

Lines changed: 1 addition & 0 deletions
Loading

src/components/HelloWorld.vue

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<script setup>
2+
import { ref } from 'vue'
3+
4+
defineProps({
5+
msg: String,
6+
})
7+
8+
const count = ref(0)
9+
</script>
10+
11+
<template>
12+
<h1>{{ msg }}</h1>
13+
14+
<div class="card">
15+
<button type="button" @click="count++">count is {{ count }}</button>
16+
<p>
17+
Edit
18+
<code>components/HelloWorld.vue</code> to test HMR
19+
</p>
20+
</div>
21+
22+
<p>
23+
Check out
24+
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
25+
>create-vue</a
26+
>, the official Vue + Vite starter
27+
</p>
28+
<p>
29+
Learn more about IDE Support for Vue in the
30+
<a
31+
href="https://vuejs.org/guide/scaling-up/tooling.html#ide-support"
32+
target="_blank"
33+
>Vue Docs Scaling up Guide</a
34+
>.
35+
</p>
36+
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
37+
</template>
38+
39+
<style scoped>
40+
.read-the-docs {
41+
color: #888;
42+
}
43+
</style>

src/main.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { createApp } from 'vue'
2+
import './style.css'
3+
import App from './App.vue'
4+
import { registerLicense } from '@syncfusion/ej2-base'
5+
registerLicense('Ngo9BigBOggjHTQxAR8/V1NCaF5cXmpCf1FpRmJGdld5fUVHYVZUTXxaS00DNHVRdkdnWXlcd3RVQ2FfUUJwVkM=')
6+
createApp(App).mount('#app')

0 commit comments

Comments
 (0)