Reputation: 1
I'm trying to figure out how to get the current changes in a 'contenteditable' and update it in the row that it was changed.
<tbody>
<!-- Loop through the list get the each data -->
<tr v-for="item in filteredList" :key="item">
<td v-for="field in fields" :key="field">
<p contenteditable="true" >{{ item[field] }}</p>
</td>
<button class="btn btn-info btn-lg" @click="UpdateRow(item)">Update</button>
<button class="btn btn-danger btn-lg" @click="DelteRow(item.id)">Delete</button>
</tr>
</tbody>
Then in the script, I want to essentially update the changes in 'UpdateRow':
setup (props) {
const sort = ref(false)
const updatedList = ref([])
const searchQuery = ref('')
// a function to sort the table
const sortTable = (col) => {
sort.value = true
// Use of _.sortBy() method
updatedList.value = sortBy(props.tableData, col)
}
const sortedList = computed(() => {
if (sort.value) {
return updatedList.value
} else {
return props.tableData
}
})
// Filter Search
const filteredList = computed(() => {
return sortedList.value.filter((product) => {
return (
product.recipient.toLowerCase().indexOf(searchQuery.value.toLowerCase()) != -1
)
})
})
const DelteRow = (rowId) => {
console.log(rowId)
fetch(`${import.meta.env.VITE_APP_API_URL}/subscriptions/${rowId}`, {
method: 'DELETE'
})
.then((response) => {
// Error handeling
if (!response.ok) {
throw new Error('Something went wrong')
} else {
// Alert pop-up
alert('Delete successfull')
console.log(response)
}
})
.then((result) => {
// Do something with the response
if (result === 'fail') {
throw new Error(result.message)
}
})
.catch((err) => {
alert(err)
})
}
const UpdateRow = (rowid) => {
fetch(`${import.meta.env.VITE_APP_API_URL}/subscriptions/${rowid.id}`, {
method: 'PUT',
body: JSON.stringify({
id: rowid.id,
date: rowid.date,
recipient: rowid.recipient,
invoice: rowid.invoice,
total_ex: Number(rowid.total_ex),
total_incl: Number(rowid.total_incl),
duration: rowid.duration
// id: 331,
// date: rowid.date,
// recipient: 'new R',
// invoice: 'inv500',
// total_ex: Number(500),
// total_incl: Number(6000),
// duration: 'Monthly'
})
})
}
return { sortedList, sortTable, searchQuery, filteredList, DelteRow, UpdateRow }
}
The commented lines work when I enter them manually:
// id: 331,
// date: rowid.date,
// recipient: 'new R',
// invoice: 'inv500',
// total_ex: Number(500),
// total_incl: Number(6000),
// duration: 'Monthly'
Each cell has content editable, I'm not sure how to update the changed event
Upvotes: 0
Views: 600
Reputation: 35684
The way these run-time js frontend frameworks work could be summarized as "content is the function of data". What I mean is the html renders the data that you send it. If you want the data to be updated when the user changes it, you need to explicitly tell it to do so. Some frameworks (like react) require you to setup 1-way data binding, so you have to explicitly define the data that is displayed in the template, as well as defining the event. Vue has added some syntactic sugar to abstract this through v-model
to achieve 2-way binding. v-model
works differently based on whichever input type you chose, since they have slightly different behaviour that needs to be handled differently. If you were to use a text input or a textarea with a v-model="item[field]"
, then your internal model would get updated and it would work. However, there is no v-model
for non-input tags like h1
or p
, so you need to setup the interaction in a 1-way databinding setup, meaning you have to define the content/value as well as the event to update the model when the html tag content changes.
have a look at this example:
<script setup>
import { ref } from 'vue'
const msg = ref('Hello World!')
</script>
<template>
<h1 contenteditable @input="({target})=>msg=target.innerHTML">{{ msg }}</h1>
<h2 contenteditable>{{ msg }}</h2>
<input v-model="msg">
</template>
If you change the h2
content, the model is not updated because vue is not tracking the changes. If you change through input
or h1
, the changes are tracked, which will also re-render the h2
and update its content.
use this:
<p
contenteditable="true"
@input="({target})=>item[field]=target.innerHTML"
>{{ item[field] }}</p>
Upvotes: 1