how to remove an uploaded images - vue.js

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>

Related

How to make disabled button after click in Vuejs

I have a button on my website that gives bonuses to the user. Button have several conditions in 1 button:
<button class="btn btn--small btn--purple" :disabled="isDisabled" #click="takeBonus">Take</button>
<script>
......
computed: {
isDisabled() {
return this.heal_used === 1 || this.diff < 10;
this.$forceUpdate();
},
},
.......
</script
But when user click Take button, and if all success, button is still active this.$forceUpdate(); not working. And i need make when user click Take button, and if all success, make this button disabled.
My full Bonus.vue:
<template>
<div class="inner-page">
<div class="account" v-if="loaded && !$root.isMobile">
<div class="page-header">
</div>
<div class="form-panels hide-below-m">
<div class="col-7" style="margin-top: 5rem;margin-right: 3rem;">
<div class="faucet-component mx-5" rv-class-boost="data.boostIsOpen">
<img src="https://dota2.skins1.games/src/img/components/shine.png?v=8ce59643e70cb2f8550deb6a249b5f29" class="faucet-component__shine-bg">
<div class="faucet-component__content d-flex justify-content-between align-items-center flex-column w-100" style="
height: 15rem;">
<div class="faucet-component__available-amount-block round-circle p-2">
<div class="faucet-component__availabe-amount-coins d-flex justify-content-center align-items-center round-circle h-100" rv-currency="model:amount">Спасение</div>
</div>
<!-- rivets: unless model:cnt | eq 0 --><div class="faucet-component__remaining">
<span rv-t="">Left</span>:
<span>{{ bonus_num }}</span><br>
<span rv-t=""></span>
<span>{{ diff }}</span>
</div>
<!-- rivets: if model:cnt | eq 0 -->
<div class="faucet-component__buttons-container d-flex align-items-center w-75 justify-content-around">
<button class="btn btn--small btn--purple" :disabled="isDisabled" #click="takeBonus">Take</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
loaded: false,
bonus: {},
diff: {},
user: {},
bonus_num: 0,
heal_used: {}
}
},
mounted() {
this.$root.isLoading = true;
if (!this.$cookie.get('token')) {
this.$root.isLoading = false;
this.$router.go(-1);
}
this.domain = window.location.protocol + '//' + window.location.hostname;
setTimeout(() => {
this.getUser();
}, 100);
},
computed: {
isDisabled() {
return this.heal_used === 1 || this.diff < 10;
this.$forceUpdate();
},
},
methods: {
getUser() {
this.$root.axios.post('/user/getProfile')
.then(res => {
const data = res.data;
console.log(data.heal_used);
console.log(data.diff);
this.loaded = true;
this.user = data.user;
this.bets = data.bets;
this.bonus = data.bonus;
this.diff = data.diff;
this.heal_used = data.heal_used;
this.new_day = data.new_day;
this.bonus_num = data.bonus_num;
this.$root.isLoading = false;
})
.catch(err => {
this.$root.isLoading = false;
this.$router.go(-1);
})
},
takeBonus() {
this.$root.axios.post('/user/takeBonus', {
value: this.user.cashback
})
.then(res => {
const data = res.data;
if (data.type === 'success') {
console.log(data.heal_used);
this.bonus_num = data.bonus_num;
this.$root.user.balance = data.newBalance;
this.heal_used = data.heal_used;
this.$forceUpdate();
}
this.$root.showNotify(data.type, this.$t(`index.${data.message}`));
})
},
}
}
How i can make it, when user click Take button, and if all success, so that the Take button becomes disabled?
I'm sorry but your code has no indentation, so I just did that on jsfiddler so you know "How to make disabled button after click in Vuejs". You can have a look on : https://jsfiddle.net/o81yvn05/1/
<div id="app">
<button :disabled="isDisabled" #click="disableButton()">Please click here</button>
</div>
<script>
new Vue({
el: "#app",
data: {
isDisabled: false,
},
methods: {
disableButton() {
this.isDisabled = true
}
}
})
</script>

Append Textarea (description) when uploading an image

I have a basic file upload in Vue.js. I am trying to append a textarea so that I can add a description about the file. However, I can not see to get this to work. The idea is to be able to send files through the API that i am creating in laravel.
<template>
<div class="container">
Files
<input type="file" id="files" ref="files" multiple v-on:change="handleFilesUpload()" />
<div v-for="(file, key) in files" :key="file.id" class="file-listing">
{{ file.name }}
<textarea
name="description"
id="description"
cols="30"
rows="10"
v-model="description"
></textarea>
<span class="remove-file" v-on:click="removeFile( key )">Remove</span>
</div>
<button v-on:click="addFiles()">Add Files</button>
<button v-on:click="submitFiles()">Submit</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
files: [],
description: ""
};
},
methods: {
addFiles() {
this.$refs.files.click();
},
submitFiles() {
let formData = new FormData();
let description = this.description;
description = JSON.stringify(description);
for (var i = 0; i < this.files.length; i++) {
let file = this.files[i];
formData.append("files[" + i + "]", file);
formData.append("description[" + i + "]", description);
}
axios
.post("/media", formData, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then(function() {
console.log("SUCCESS!!");
})
.catch(function() {
console.log("FAILURE!!");
});
},
handleFilesUpload() {
let uploadedFiles = this.$refs.files.files;
for (var i = 0; i < uploadedFiles.length; i++) {
this.files.push(uploadedFiles[i]);
}
},
removeFile(key) {
this.files.splice(key, 1);
}
}
};
</script>
I am trying to add a description for each file. Does anyone have any ideas please?
Here there is one description model but we need a description model for each file.
So let define them
<template>
<div class="container">
Files
<input
id="files"
ref="files"
type="file"
multiple
#change="handleFilesUpload()"
/>
<div v-for="(item, key) in files" :key="key" class="file-listing">
{{ item.file.name }}
<textarea
v-model="item.description"
name="description"
cols="30"
rows="10"
></textarea>
<span class="remove-file" #click="removeFile(key)">Remove</span>
</div>
<button #click="addFiles()">Add Files</button>
<button #click="submitFiles()">Submit</button>
</div>
</template>
<script>
export default {
data() {
return {
files: [],
description: ''
}
},
methods: {
addFiles() {
this.$refs.files.click()
},
submitFiles() {
let formData = new FormData()
for (var i = 0; i < this.files.length; i++) {
let item = this.files[i]
formData.append('files[' + i + ']', item.file)
formData.append('description[' + i + ']', item.description)
}
axios
.post('/media', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(function() {
console.log('SUCCESS!!')
})
.catch(function() {
console.log('FAILURE!!')
})
},
handleFilesUpload() {
let uploadedFiles = this.$refs.files.files
for (var i = 0; i < uploadedFiles.length; i++) {
this.files.push({
file: uploadedFiles[i],
description: ''
})
}
},
removeFile(key) {
this.files.splice(key, 1)
}
}
}
</script>
See working example here
<div class="field relative">
<label>Description</label>
<textarea class="textarea" v-model="description" type="text" maxlength="10000"> </textarea>
<label for="upload-file" class="icn icn-camera cursor-pointer absolute bottom-3 right-4">
<input type="file" id="upload-file" hidden ref="file" #change="getImage($event)" accept="image/**" />
</label>
</div>
use Relative and Absolute position to put the camera icon inside the
textarea
use bottom-3 right-4 to find the proper position
change the default upload file icon to a camera icon

Vue Get uploaded files url

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

Vue Axios form sending empty data instead of image

Alright so I am trying to send image data using JSON but no matter what I do I always end up in sending an empty object... I've tried to console log results but no matter what it just sends empty object
CODE:
<body>
<div id="app">
<div v-if="!image">
<h2>Select an image</h2>
<input type="file" #change="onFileChange" multiple>
</div>
<div v-else>
<div v-for="img in image" class="img_overlay">
<img :src="img" class="img_set"/><br/>
<button #click="removeImage(img)">Remove image</button>
</div>
</div>
</div>
<style>
.img_overlay {
width: 25%;
height: 250px;
float: left;
text-align: center;
}
img {
width: 250px;
height: 200px;
}
</style>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
image: "",
file_data: []
},
methods: {
onFileChange(e) {
var files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
else if(files.length == 1)
this.createImage(files)
else if(files.length >= 2)
this.createImage(files)
this.file_data = e.target.files;
this.uploadImage(e.target.files);
},
createImage(file) {
var tmp = [];
for(let i = 0; i < file.length; i++) {
var image = new Image();
var reader = new FileReader();
var vm = this;
reader.onload = (e) => {
tmp.push(e.target.result);
};
reader.readAsDataURL(file[i]);
}
vm.image = tmp;
},
removeImage: function (img) {
for(let i = 0; i < this.image.length; i++) {
if(this.image[i] == img) {
this.image.splice(i, 1);
}
}
},
uploadImage: function(x_file) {
const config = {
headers: { 'content-type': 'multipart/form-data' }
}
axios.post('/theme/post_new_image', x_file, config).then(function (response) {
console.log(response);
}).catch(e => { console.log(e); });
}
}
});
</script>
</body>
The result I usualy get is empty object with 5 keys. I've tried to stringify the data and such but I've couldn't find the correct solution for it
You are passing an array of files to your uploadImage function. Try iterating over the array to upload each file:
for (var i = 0, f; f = e.target.files[i]; i++) {
uploadImage(f);
}

VueJS 2 update contenteditable in component from parent method

I have editable element updated by component method, but i have also json import and i want to update element my parent method. I can update model, but editable element doesn´t bind it. If i insert content to component template, it will bind updated model, but then i can´t really edit it.
Here´s my example: https://jsfiddle.net/kuwf9auc/1/
Vue.component('editable', {
template: '<div contenteditable="true" #input="update"></div>', /* if i insert {{content}} into this div, it wil update, but editing behave weird */
props: ['content'],
mounted: function () {
this.$el.innerText = this.content;
},
methods: {
update: function (event) {
console.log(this.content);
console.log(event.target.innerText);
this.$emit('update', event.target.innerText);
}
}
})
var app = new Vue({
el: '#myapp',
data: {
herobanner: {
headline: 'I can be edited by typing, but not updated with JSON upload.'
}
},
methods: {
uploadJSON: function (event) {
var input = event.target;
input.src = URL.createObjectURL(event.target.files[0]);
var data = input.src;
$.get(data, function(data) {
importdata = $.parseJSON(data);
this.$data.herobanner = importdata.herobanner;
}.bind(this));
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<main id="myapp" class="container-fluid">
<input type="file" id="file" name="file" #change="uploadJSON" style="display: none; width: 1px; height: 1px"/>
<a href="" onclick="document.getElementById('file').click(); return false" title="Import settings from JSON file">
upload JSON
</a>
<h1>
<editable :content="herobanner.headline" #update="herobanner.headline = $event"></editable>
</h1>
Real value of model:
<br>
<h2>{{herobanner.headline}}</h2>
</main>
Working example:
Vue.component('editable', {
template: `
<div contenteditable="true" #blur="emitChange">
{{ content }}
</div>
`,
props: ['content'],
methods: {
emitChange (ev) {
this.$emit('update', ev.target.textContent)
}
}
})
new Vue({
el: '#app',
data: {
herobanner: {
headline: 'Parent is updated on blur event, so click outside this text to update it.'
}
},
methods: {
async loadJson () {
var response = await fetch('https://swapi.co/api/people/1')
var hero = await response.json()
this.herobanner.headline = hero.name
},
updateHeadline (content) {
this.herobanner.headline = content
}
}
})
<main id="app">
<button #click="loadJson">Load JSON data</button>
<h1>
<editable
:content="herobanner.headline"
v-on:update="updateHeadline"
>
</editable>
</h1>
<h2>{{herobanner.headline}}</h2>
</main>
<script src="https://unpkg.com/vue#2.5.3/dist/vue.min.js"></script>