I want to do a text-correction, where I can click the wrong words and choose a correction from the list(somewhat like Grammarly does).
This simple example should help you understand the idea. Let's assume I have a list of objects returned from a server:
data: {
objects: [
{
word: "This",
val: 0.1,
corrections: {"that", "Those"}
},
{
word: "kat",
val: 0.9,
corrections: {"cat", "cats", "dogs", "animals"}
}
]
}
Now I want to write a v-for which will:
val < 0.5
just display a word
val >= 0.5
display a word
with a red underline, and an ability to click and see a drop-down list with all corrections
word
after choosing an option in the drop-down.Minimal reproducible (not working) example:
Vue.component('post-list', {
data: function() {
return {
objects: [{
word: "This",
val: 0.1,
corrections: [
"that",
"Those"
]},
{
word: "kat",
val: 0.9,
corrections: [
"cat",
"cats",
"dogs",
"animals"
]}
]
}
},
});
new Vue({
el: '#vue-app'
});
<script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="vue-app" class="container">
<post-list inline-template>
<div>
<template class="post" v-for="object in objects">
{{ object.word }}
</template>
</div>
</post-list>
</div>
So basically you are asking us to create a copy of "Grammarly" for you in like 10 minutes?
A'ight, challenge accepted. I've create a working but rough example to give you a starting point and perhaps some ideas on how to improve it. Keep in mind that it's not the best solution since I didn't put a lot of time and thought into it:
Also, I would move the getFormattedData()
method to the server, so that you get formatted data with underlined
properties along with val
and corrections
instead of re-computing it on the client side.
<v-menu
v-model="correctionsListIsVisible"
>
<v-list dense>
<v-list-item
v-for="(correction, index) in correctionsListItems"
:key="index"
@click="applyCorrection(correction)"
>
<v-list-item-content>
<v-list-item-title>
{{correction}}
</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-menu>
<div class="flex">
<div v-for="(object, index) in getFormattedData" class="flex">
<div
@click="toggleCorrectionsList(object)"
:class="{'underlined': object.underlined}"
id="word"
>{{ object.word }}
</div>
<div v-if="addSpace(index)"> </div>
</div>
</div>
data () {
return {
correctionsListIsVisible: false,
correctionsListItems: [],
activeObject: {},
objects: [
{
word: "This",
val: 0.1,
corrections: ["that", "Those"]
},
{
word: "kat",
val: 0.9,
corrections: ["cat", "cats", "dogs", "animals"]
},
{
word: "is",
val: 0.1,
corrections: []
},
{
word: "cute",
val: 0.2,
corrections: []
},
]
}
},
computed: {
getFormattedData() {
let result = []
for (const item of this.objects) {
let object = {}
if (item.val < 0.5) {
object.word = item.word
object.underlined = false
object.corrections = []
}
else if (item.val >= 0.5) {
object.word = item.word
object.underlined = true
object.corrections = item.corrections
}
result.push(object)
}
return result
}
},
methods: {
addSpace (index) {
return index !== (this.getFormattedData.length - 1)
},
toggleCorrectionsList (object) {
if (object.underlined) {
this.correctionsListItems = object.corrections
this.activeObject = object
this.correctionsListIsVisible = true
}
else {
this.activeObject = {}
}
},
applyCorrection (correction) {
this.activeObject.word = correction
this.activeObject.underlined = false
}
}