javascriptlaravelvue.jsvuejs2

Vue v-model.lazy or @change does not update my Vue data


With chrome build in voice recognition I change the textarea value with spoken words. After the value changes, my vue data does not update.

I already tried v-model.lazy, @change, and v:bind.

Vue template

<div class="form-group">
    <textarea v-model.lazy="textboxInput" contenteditable="true" @change="onDivInput($event) " class="form-control" id="result" rows="1" name="inputData"></textarea>
 </div>

Vue code

export default {
    data() {
        return {
            result: [],
            textboxInput: '',
            session_id: this.sessionid,
            user: this.userid,
            edit: false,
            roundRobin: JSON.parse(this.roundrobin),
        }
    },
    props: {
        sessionid: '',
        userid: '',
        roundrobin: '',

    },
    mounted() {
        this.getResult();
        this.listen();
        this.mod();

    },


    methods: {
        onDivInput: function (e) {

            this.textboxInput = e.target.innerHTML;
            console.log(e);
        },

Javascript where textarea value changes R is the textarea

try {
    let finalTranscripts = '';
    if ('webkitSpeechRecognition' in window && hasUserMedia) {
        let speechRecognizer = new webkitSpeechRecognition();
        speechRecognizer.continuous = false;
        speechRecognizer.interimResults = true;
        speechRecognizer.lang = 'nl-be';
        speechRecognizer.start();



        speechRecognizer.onresult = function (event) {
            let interimTranscripts = '';
            for (let i = event.resultIndex; i < event.results.length; i++) {
                let transcript = event.results[i][0].transcript;
                transcript.replace("\n", "<br>");
                if (event.results[i].isFinal) {
                    finalTranscripts += transcript;
                } else {
                    interimTranscripts += transcript;
                }
            }
            r.innerHTML = finalTranscripts + interimTranscripts;


        }


        ;
        speechRecognizer.onerror = function (event) {
            speechRecognizer.stop();
        };
    } else {
        r.innerHTML = 'Your browser is not supported. If google chrome, please upgrade!';
    }
} catch (ex) {
    e.innerHTML = ex;
}

If the innerhtml of the textarea changes i want that my data updates aswell.


Solution

  • Docs on v-model.lazy

    By default, v-model syncs the input with the data after each input event (with the exception of IME composition as stated above). You can add the lazy modifier to instead sync after change events.

    Right now you're using both v-model.lazy (which syncs after change events) and @change (which, whats in the name, also listens to change events). That's one too many. v-model.lazy="textboxInput" is actually a shortcode for :value="textboxInput" @change="textboxInput = $event.target.value". So you're actually listening to @change twice.

    You can just use

    <textarea v-model.lazy="textboxInput" contenteditable="true" class="form-control" id="result" rows="1" name="inputData"></textarea>
    

    Which already syncs the value of e.target.value back to your prop.

    If you want to textboxInput to listen to input, you should remove the .lazy modifier.