1
votes

I try to make a typing program for one of my students. I use SVG to generate the words, and use class binding with vuejs. the color of the characters should change when the user presses the right key. But for some reason it is not working. Can somebody tell me where I went wrong?

When I assign a change to the array, with a button click, it works. And when I console.log the array after keypress, the array is changed, but the color of the character isn't!

export default {

    data(){
        return{
            word:["a","p","p","e","l","m","o","e","s"],
            letterId:0,
            kleur:[false,false,false,false,false,false,false,false,false],
         }
    },
    methods:{
        checkLetter(event){
            console.log('key pressed: ' + event.which)
            console.log('letter' +this.letterId+' is: ' + this.letter)
            
            if(event.key == this.letter){
                console.log("correct key was pressed")
                this.kleur[this.letterId] = true
                this.letterId++
            }
        }
    },
    computed:{
        
        letter(){
            //determine  which letter is expected
            return this.word[this.letterId]
        },
        viewbox(){
            //adjust viewbox according to the length of the word
            var width = (this.word.length * 50) + 50
            return "0 0 "+width + " 70"
        }

    },
    created: function () {
            window.addEventListener('keyup', this.checkLetter)
    },


}
.green{
    font: bold 35px Courier;
    fill:green;
}
.normaal{
   font: bold 35px Courier;
    fill:black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template>
<div> 
    <svg :viewBox="viewbox" width="100%">
        <text v-for="letter,index in word" :x="index*40" y="45"  :id="index" :class="{green:kleur[index], normaal:!kleur[index]}">{{letter}}</text>
     </svg>   
    </div>
</template>
2
I'm not sure what in this template is reactive? Look at it this way: there is an observer checking if your DOM would need a redraw. And if you change things inside an Array nothings is changed. Nothing in your template is changed. If you would add :data-redraw="letterId" in your <svg then that would change and your svg is redrawn. - Joeri

2 Answers

0
votes

Look. I just changed eveything.

Add this to your methods. and delete it from computed.

//finds the letter in the array and returns it 
letter(letter){
              return this.word.find(element => {
                  return element == letter;
              })
        },

Then I changed checkLetter to this

checkLetter(event){
            console.log('eventkey: ' + this.letter(event.key));
            //if it finds it then the correct key wes pressed. 
            if(event.key == this.letter(event.key)){
                console.log("correct key was pressed")
                this.kleur[this.letterId] = true
                this.letterId++
            }
        }
0
votes

I've found a solution. But I don't understand why it is working. I just added a variable called 'test' to my data. And in the checkletter method I added one line to assign the test var to the stringified array, like this

checkLetter(event){
            console.log('key pressed: ' + event.which)
            console.log('letter' +this.letterId+' is: ' + this.letter)

            if(event.key == this.letter){
                console.log("correct key was pressed")
                this.kleur[this.letterId] = true
                //modification
                this.test = this.kleur.toString()
                this.letterId++


            }
        }

In the html template, i also added a hidden div where i output the test value.