vue.jsv-forerror-correction

How to make v-for drop-down text with a function?


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:

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>


Solution

  • 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:

    Demo https://codepen.io/aQW5z9fe/pen/MWaQjdX

    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)">&nbsp;</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
      }
    }