I am using vue and element ui to upload files. But I don't know how to get upload files url (basically I want to check the file type - jpg or pdf and then do something).
<div id="app">
<el-upload action="https://jsonplaceholder.typicode.com/posts/" list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<embed width="100%" :src="dialogImageUrl">
</el-dialog>
<p>file type: "{{ checkType() }}"</p>
</div>
var Main = {
data() {
return {
dialogImageUrl: '',
dialogVisible: false
};
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
checkType(){
var filename = this.dialogImageUrl;
return filename.split('.').pop();
}
}
}
Please Help...
I have add this try to get URL..but it doesn't work..
var filename = document.getElementsByTagName("embed")[0].src;
console.log(filename);
you can use :before-upload attribute of el-upload. please take look of changed code.
<div id="app">
<el-upload action="https://jsonplaceholder.typicode.com/posts/" **:before-upload="checkType"** list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<embed width="100%" :src="dialogImageUrl">
</el-dialog>
<p>file type: "{{ checkType() }}"</p>
</div>
var Main = {
data() {
return {
dialogImageUrl: '',
dialogVisible: false
};
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
**checkType(file){**
console.log(file.type);
// do your action here based on file.type
var filename = this.dialogImageUrl;
return filename.split('.').pop();
}
}
}
Related
Here I have tried to remove a uploaded images. Like while if user clicks on any of the images which is uploaded by the user if we click on cross icon it has to remove the images. So below is my code where I have tried and I am able to remove the image but at once multiple images are removing i need to remove only selected images not multiple so how can we do that. all images should have cross icon at the top corner. Please
Vue.config.productionTip = false;
new Vue({
el: '#app',
data() {
return {
files: [],
images: null,
}
},
computed: {
filesNames() {
const fn = []
for (let i = 0; i < this.files.length; ++i) {
fn.push(this.files.item(i).name)
}
return fn
}
},
methods: {
handleFileUploads(event) {
this.files = event.target.files;
this.images = [...this.files].map(URL.createObjectURL);
},
removeImage: function () {
this.images = null
},
submitFile() {
let formData = new FormData();
for (var i = 0; i < this.files.length; i++) {
let file = this.files[i];
formData.append('files[' + i + ']', file);
}
axios.post('/multiple-files', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(function() {
console.log('SUCCESS!!');
})
.catch(function() {
console.log('FAILURE!!');
});
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<div id="app">
<h2>Multiple Files</h2>
<hr/>
<label>
<span>Files</span>
<input type="file" multiple #change="handleFileUploads($event)" />
<ul v-if="files.length">
<li v-for="(name, i) in filesNames" :key="i">{{ name }}</li>
</ul>
</label>
<div>
<img v-for="image in images" :src="image" />
<button v-if="images" #click="removeImage()" type="button">×</button>
</div>
<br />
<button #click="submitFiles()">Submit</button>
</div>
i'm trying to make work Laravue Dropzone, but I have'nt working yet
Here is the code:
<el-dialog :title="'Importar Bitacora'" :visible.sync="dialogFormVisible">
<div v-loading="weblogCreating" class="form-container">
<el-form ref="weblogForm" :rules="rules" :model="newBitacora" label-position="left" label-width="150px">
<div class="editor-container">
<dropzone id="CargarBitacora" url="/api/bitacora/importar" #dropzone-removedFile="dropzoneR(e)" #dropzone-error="dropzoneError" #dropzone-success="dropzoneS" />
</div>
</el-form>
</div>
<div slot="footer" class="dialog-footer">
<el-button #click="dialogFormVisible = false">
{{ $t('bitacora.cancel') }}
</el-button>
<el-button type="primary" #click="handleUpload()">
{{ $t('bitacora.confirm') }}
</el-button>
</div>
</el-dialog>
<script>
import Dropzone from '#/components/Dropzone';
export default {
name: 'BitacoraList',
components: { Dropzone },
data() {
return {
files: [],
},
created() {
.. code here ..
},
methods: {
handleUpload(e) {
const formData = new FormData();
this.files.forEach(file => {
formData.append('files[]', file);
});
console.log(this.files);
},
}
};
</script>
I've tried to pass the files to handleUpload, but I can't make it work to the moment
I figured out how to upload files with dropzone, en the method handleUpload I just have to send the file to a post method in laravel backend who upload a temporary file
dropzoneR(file) {
var name = file.upload.filename;
fileResource.borrar(name).then(response => {
this.files.splice(this.files.indexOf(name), 1);
if (this.files.length < 1) {
this.btnUpload = true;
}
}).catch(error => {
console.log(error);
});
},
and returns an ok if it gets uploaded, then when I confirm thats the files I need up, other method in laravel backend who do what a want to do with the file if its an excel file (in mi case) upload the data to the database, or what ever I want. like this
async handleUpload(e) {
this.weblogCreating = true;
await bitacoraResource.store(this.files).then(response => {
this.$message({ message: 'Bitacoras importadas satisfactoriamente', type: 'success' });
this.files = '';
this.dialogImportVisible = false;
this.weblogCreating = false;
this.getList();
}).catch(error => {
this.$message({
message: 'Error importando las bitacoras ' + error.getMessage,
type: 'error',
});
this.weblogCreating = false;
console.log(error.message);
});
},
i dont know if this is possible - but i am working on a Vue app with multiple input fields that posts to the same list - and i need this to be stored somehow, so when you refresh the site, the outputs from the input fields are saved.
This means both the taskList and subTaskList array should be saved ( i know i've only worked on taskList ).
The example i posted here saves the data fine, however if you refresh, it will post all the data in all the components, can this be fixed so it will only be in the right components?
const STORAGE_KEY = 'madplan-storage'
Vue.component('list-component', {
data: function() {
return {
newTask: "",
taskList: [],
newSubTask: "",
subTaskList: [],
};
},
created() {
this.taskList = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
},
template:
'<div>' +
'<section class="prefetch">' +
'<input v-if="showInput" class="input typeahead" type="text" placeholder="Tilføj ret til madplanen" v-model="newTask" v-on:keyup.enter="addTask">' +
'</section>' +
'<details open v-for="task in taskList" v-bind:key="task.text" class="sub-list-item">' +
'<summary>{{ task.text }}<i class="fa fa-times" aria-hidden="true" v-on:click="removeTask(task)"></i>' + '</summary>' +
'<input class="subInput" type="text" placeholder="Tilføj til indøbsseddel" v-model="newSubTask" v-on:keyup.enter="addSubTask">' +
'</details>' +
'</div>',
computed: {
showInput: function() {
return !this.taskList.length
},
},
methods: {
//addTasks
//
addTask: function() {
var task = this.newTask.trim();
if (task) {
this.taskList.push({
text: task
});
this.newTask = "";
localStorage.setItem(STORAGE_KEY, JSON.stringify(this.taskList));
}
},
addSubTask: function() {
var task = this.newSubTask.trim();
if (task) {
this.subTaskList.push({
text: task
});
this.newSubTask = "";
this.$emit('addedtask', task);
localStorage.setItem(STORAGE_KEY, JSON.stringify(this.subTaskList));
}
},
//removeTasks
//
removeTask: function(task) {
var index = this.taskList.indexOf(task);
this.taskList.splice(index, 1);
},
},
});
new Vue({
el: "#madplan",
data: {
newTask: "",
taskList: [],
newSubTask: "",
subTaskList: [],
},
methods: {
acknowledgeAddedTask: function(cls, task) {
this.$data.subTaskList.push({
text: task,
class: "list-item " + cls
})
},
acknowledgeRemovedTask: function(task) {
this.$data.subTaskList = this.$data.subTaskList.filter(it => it.text != task.text)
},
removeSubTask: function(task) {
var index = this.subTaskList.indexOf(task);
this.subTaskList.splice(index, 1);
},
}
});
<section id="madplan" class="section-wrapper">
<section class="check-list">
<div id="mandag" class="dayWrapper">
<h1>Day One</h1>
<list-component
class="mandag"
v-on:addedtask='task => acknowledgeAddedTask("mandag", task)'
></list-component>
</div>
<div id="tirsdag" class="dayWrapper">
<h1>Day Two</h1>
<list-component
class="tirsdag"
v-on:addedtask='task => acknowledgeAddedTask("tirsdag", task)'
></list-component>
</div>
<ul id="indkobsseddel">
<h2>Shopping List</h2>
<li v-for="task in subTaskList" v-bind:key="task.text" :class="task.class">{{ task.text }}<i class="fa fa-times" aria-hidden="true" v-on:click="removeSubTask(task)"></i></li>
</ul>
</section>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js" charset="utf-8"></script>
To be clear, i will come with an example:
As it is now, if i post "Foo" and "Bar" to the "Day One" component and refresh the page, it will then post "Foo" and "Bar" to both "Day One" and "Day Two".
Essentially, i would like to be able to post for an example "Foo" to "Day One", "Bar" to "Day Two" and from there post "Hello World" to the Shopping List, and it would all be saved in the right places, instead of posting everything everywhere.
BTW: I'm a scrub at backend work.
To persist global state, you may use the plugin vue-persistent-state like this:
import persistentStorage from 'vue-persistent-storage';
const initialState = {
newTask: "",
taskList: [],
newSubTask: "",
subTaskList: [],
};
Vue.use(persistentStorage, initialState);
Now newTask, taskList, newSubTask and subTaskList is available as data in all components and Vue instances. Any changes will be stored in localStorage, and you can use this.taskList etc. as you would in a vanilla Vue app.
Your list component now becomes:
Vue.component('list-component', {
// data removed
// created removed
template:
'<div>' +
'<section class="prefetch">' +
'<input v-if="showInput" class="input typeahead" type="text" placeholder="Tilføj ret til madplanen" v-model="newTask" v-on:keyup.enter="addTask">' +
'</section>' +
'<details open v-for="task in taskList" v-bind:key="task.text" class="sub-list-item">' +
'<summary>{{ task.text }}<i class="fa fa-times" aria-hidden="true" v-on:click="removeTask(task)"></i>' + '</summary>' +
'<input class="subInput" type="text" placeholder="Tilføj til indøbsseddel" v-model="newSubTask" v-on:keyup.enter="addSubTask">' +
'</details>' +
'</div>',
computed: {
showInput: function() {
return !this.taskList.length
},
},
methods: {
//addTasks
//
addTask: function() {
var task = this.newTask.trim();
if (task) {
this.taskList.push({
text: task
});
this.newTask = "";
// localStorage.setItem not needed
}
},
addSubTask: function() {
var task = this.newSubTask.trim();
if (task) {
this.subTaskList.push({
text: task
});
this.newSubTask = "";
// $emit not needed, state is global and shared
// localStorage.setItem not needed
}
},
//removeTasks
//
removeTask: function(task) {
var index = this.taskList.indexOf(task);
this.taskList.splice(index, 1);
},
},
});
If you want to understand how this works, the code is pretty simple. It basically
adds a mixin to make initialState available in all Vue instances, and
watches for changes and stores them.
Disclaimer: I'm the author of vue-persistent-state.
Can someone help me on how to upload a file on pouchdb and display those uploaded files on page. I want to upload a file including name info of that file. When I check the fetch files using the console I can see [object object]. Am I doing the right thing? Any advice is well appreciated. Here is my code.
//Notes.vue
// By the way Im using onsen ui for this
<template>
<v-ons-page>
<v-ons-list>
<v-ons-list-header>Auditing</v-ons-list-header>
<v-ons-list-item v-for="note in notes">
<div class="left">
<img src="" alt="">
</div>
<div class="center">
<span>{{ note._attachment['files'].data }} File here</span>
</div>
</v-ons-list-item>
</v-ons-list>
// Customize form for uploading file and info
<v-ons-alert-dialog
modifier="rowfooter"
:visible.sync="dialogVisible"
>
<span slot="title">Create a Note</span>
//File name of the file
<v-ons-input float
placeholder="Name of note"
v-model="name"
>
</v-ons-input>
// File
<v-ons-input type="file" #change="onFileChange"></v-ons-input>
<v-ons-button #click="addNotes(name)">Submit</v-ons-button>
</v-ons-alert-dialog>
</v-ons-page>
</template>
//Here the methods for uploading and reading file uploaded
<script>
import PouchDB from 'pouchdb'
var db = new PouchDB('reviewerdb')
export default {
data() {
return {
dialogVisible: false,
notes: [],
file: '',
name: '',
path
}
},
mounted() {
this.getNotes();
print('notes: ' + this.notes);
},
//Methods just adding a desciption
methods: {
onFileChange(event) {
this.file = event.target.files[0];
},
addNotes() {
db.put({
_id: 'notes',
_attachments: {
"file": {
type: this.file.type,
data: this.file
}
}
})
},
getNotes() {
db.get('notes', {attachments:true}).then(function (note) {
this.notes = note;
});
}
}
}
I am currently previewing an image, but would also like to actually return somehow the file to my form, so that I can later submit it in the backend, but not sure how to do that?
This is my component:
<template>
<div>
<div v-if="!image">
<h2>Select an image</h2>
<input type="file" #change="onFileChange">
</div>
<div v-else>
<img :src="image" />
<button #click="removeImage">Remove image</button>
<input type="file" v-bind:value="{ file }" style="display:none">
</div>
</div>
</template>
<script>
export default {
data() {
return {
image: '',
formData:new FormData()
}
},
methods: {
onFileChange: function onFileChange(e) {
var files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
this.createImage(files[0]);
this.formData.append('file', files[0]);
},
createImage: function createImage(file) {
var image = new Image();
var reader = new FileReader();
var vm = this;
reader.onload = function (e) {
vm.image = e.target.result;
};
reader.readAsDataURL(file);
},
removeImage: function removeImage(e) {
this.image = '';
}
}
}
</script>
I have tried with adding formData:new FormData() to data function and then appending the file to formData object like this:
this.formData.append('file', files[0]);
But I get an error:
formData is not defined
Hi I think the error caused by v-bind:value="{ file } , you should remove it, and it will work:
<input type="file" style="display:none">
You can't use v-model = "file" to get the file data, and what you have done with this.formData.append('file', files[0]); is the right way to get the data, if you want to get the data in the scope of your components, you can do something like this:
data() {
return {
image: '',
formData:new FormData(),
file: null
}
},
methods: {
onFileChange: function onFileChange(e) {
var files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
this.createImage(files[0]);
this.formData.append('file', files[0]);
this.file = files[0];
}
....
reference:
https://laracasts.com/discuss/channels/vue/vuejs-using-v-model-with-input-typefile?page=1
http://codepen.io/Atinux/pen/qOvawK/