i have a component that pulls data from db and display it in bootstrap cards. when i click the edit button the modal shown and passed to the input. when i change the input value, the card title changes as well, and i find no way to prevent it, while i didn't even coded it.
my guess is that the issue is with the v-model but i couldn't find any other way to pass my data to the modal edit form. i'm a vuejs newbie so it might be related to that
i don't look for an explanation about how reference object works, i wonder why the DOM getting rendered and how can i prevent this behavior
my component attached below
<template>
<div>
<div class="container">
<div class="row">
<div class="col-12">
<p>
<b-button id="show-btn" variant="primary" v-b-modal.add-product v-on:click="addProduct()"><font-awesome-icon icon="plus" /> Create Product</b-button>
</p>
</div>
</div>
<div class="row">
<b-card
:title="product.title"
:img-src="product.image"
img-alt="Image"
img-class="product_image"
img-top
tag="article"
class="col-4 mb-2"
v-for="product in products" :key="product.id"
>
<div>
<b-button href="#" variant="outline-primary" v-b-modal.add-product v-on:click="editProduct(product)">Edit</b-button>
</div>
</b-card>
</div>
</div>
<b-modal ref="add-product" id="add-product" hide-footer title="create/edit product" size="xl" >
<div class="d-block text-center">
<div v-if="!edit">
<form v-on:submit.prevent="create" enctype="multipart/form-data">
<div class="row">
<div class="col-12 col-md-6">
<div class="form-group">
<label>Product Name</label>
<input type="text" name="product_name" id="product_name" v-model="form.title" class="form-control" /><br>
</div>
</div>
<div class="col-12 col-md-6">
<div class="form-group">
<label>Picture</label>
<input class="form-control" type="file" ref="file" @change="onSelect" />
</div>
</div>
</div>
<input type="submit" value="save" class="btn btn-primary" />
</form>
</div>
<div v-else>
<form v-on:submit.prevent="save" enctype="multipart/form-data">
<div class="row">
<div class="col-12 col-md-6">
<div class="form-group">
<label>Create Product</label>
<input type="text" name="product_name" id="product_name_edit" v-model="productEdit.title" class="form-control" /><br>
</div>
</div>
<div class="col-12 col-md-6">
<div class="form-group">
<label>Picture</label>
<input class="form-control" type="file" ref="file" @change="onSelect" />
</div>
</div>
</div>
<input type="submit" value="Save" class="btn btn-primary" />
</form>
</div>
</div>
</b-modal>
</div>
</template>
<script>
import { library } from '@fortawesome/fontawesome-svg-core'
import { faPlus } from '@fortawesome/free-solid-svg-icons'
library.add(faPlus)
import axios from "axios"
import router from "../router"
export default {
name: "Products",
components:{
},
data() {
return {
products:[],
form: {
title: ''
},
productEdit: '',
edit: false,
}
},
methods: {
del() {
addProduct() {
this.edit = false
},
editProduct(p) {
this.edit = true;
this.productEdit = p;
},
onSelect(){
const allowedTypes = ["image/jpeg", "image/jpg", "image/png"];
const file = this.$refs.file.files[0];
this.file = file;
if(!allowedTypes.includes(file.type)){
this.$swal('oops,'image only,'error')
}
},
async create() {
const formData = new FormData();
formData.append('file',this.file);
formData.append('title',this.form.title);
try{
await axios.post('/api/createproduct',formData).then(function(response){
if (response.data.status=="ok") {
this.getProducts()
}
});
}
catch(err){
console.log(err);
this.message = err.response.data.error
}
},
showModal() {
this.$refs['add-product'].show()
},
hideModal() {
this.$refs['add-product'].hide()
},
toggleModal() {
// We pass the ID of the button that we want to return focus to
// when the modal has hidden
this.$refs['add-product'].toggle('#toggle-btn')
},
getProducts() {
axios.get("/api/products").then((response) => {
response.data.forEach((item) => {
this.products.push(item)
});
}).catch((errors) => {
console.log(errors)
})
}
},
mounted() {
this.getProducts()
}
}
</script>