Search code examples
javascriptvue.jssalesforce

vuejs3 - update computed value from v-model


I'm using vue-3

I am not familiar with vuejs and I am a newbie developer.

Situation

To add translations in batch on salesforce I wanted to code a tool. I coded a webservice in rust which gets a json and turns it into a zip for salesforce.

The client provides me with data from a spreadsheet, and I have to format it in json to send it to my webervice. I wanted to allow a copy / paste in a cell then split each line with "\ n" that I link to an input in order to edit the entry if necessary.

Problem

The input fill well with splited values, but if I change the input, the value in "computed" does not update. see image here

Questions

How can I update my value in my computed array with splited values ? V-model update my input from the computed but not the reverse. what is the best function to do this? I saw that there is reactive but I do not know if this is the right solution.

Here my code

<template>
<div>
    <label for="fr">fr</label>
    <input type="checkbox" value="fr" id="fr" v-model="fr.state" />

    <label for="en">en</label>
    <input type="checkbox" value="en" id="en" v-model="en.state" />

    <label for="it">it</label>
    <input type="checkbox" value="it" id="it" v-model="it.state" />

    <label for="es">es</label>
    <input type="checkbox" value="es" id="es" v-model="es.state" />

    <label for="german">german</label>
    <input type="checkbox" value="german" id="german" v-model="german.state" />
</div>

{{ formated.fr }}

<div class="Array">
    <table>
        <thead>
            <tr>
                <th>The table header</th>
                <th>default Value</th>
                <th v-if="fr.state === true">fr</th>
                <th v-if="en.state === true">en</th>
                <th v-if="it.state === true">it</th>
                <th v-if="es.state === true">es</th>
                <th v-if="german.state === true">german</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>C/C</td>
                <td><textarea v-model="defaultentry" cols="40" /></td>
                <td v-if="fr.state === true"><textarea v-model="fr.value" cols="40" /></td>
                <td v-if="en.state === true"><textarea v-model="en.value" cols="40" /></td>
                <td v-if="it.state === true"><textarea v-model="it.value" cols="40" /></td>
                <td v-if="es.state === true"><textarea v-model="es.value" cols="40" /></td>
                <td v-if="german.state === true">
                    <textarea v-model="german.value" cols="40" />
                </td>
            </tr>
            <tr v-for="(entry, index) in formated.default" :key="index">
                <td v-if="formated.default[index]">{{ index }}</td>
                <td v-if="formated.default[index]">
                    <input type="text" v-model="formated.default[index]" />
                </td>
                <td v-if="formated.fr">
                    <input type="text" v-model="formated.fr[index]" />
                </td>
                <td v-if="formated.en">
                    <input type="text" v-model="formated.en[index]" />
                </td>
                <td v-if="formated.it">
                    <input type="text" v-model="formated.it[index]" />
                </td>
                <td v-if="formated.es">
                    <input type="text" v-model="formated.es[index]" />
                </td>
                <td v-if="formated.german">
                    <input type="text" v-model="formated.german[index]" />
                </td>
            </tr>
        </tbody>
    </table>
</div>
<script>
export default {
name: "Array",
entries: {},

data() {
    return {
        defaultentry: [],
        fr: { state: false, value: [] },
        en: { state: false, value: [] },
        it: { state: false, value: [] },
        es: { state: false, value: [] },
        german: { state: false, value: [] },
    };
},

computed: {
    formated: function() {
        let entries = {};

        let base = this.defaultentry
            .toString()
            .split("\n")
            .map((x) => {
                if (x.length > 40) {
                    return "error";
                }
                return x.trim();
            });
        let fr = this.fr.value
            .toString()
            .split("\n")
            .map((x) => {
                if (x.length > 40) {
                    return "error";
                }
                return x.trim();
            });
        let en = this.en.value
            .toString()
            .split("\n")
            .map((x) => {
                if (x.length > 40) {
                    return "error";
                }
                return x.trim();
            });
        let it = this.it.value
            .toString()
            .split("\n")
            .map((x) => {
                if (x.length > 40) {
                    return "error";
                }
                return x.trim();
            });
        let es = this.es.value
            .toString()
            .split("\n")
            .map((x) => {
                if (x.length > 40) {
                    return "error";
                }
                return x.trim();
            });
        let german = this.german.value
            .toString()
            .split("\n")
            .map((x) => {
                if (x.length > 40) {
                    return "error";
                }
                return x.trim();
            });

        entries.default = base;
        if (this.fr.state == true) {
            entries.fr = fr;
        } else {
            delete entries.fr;
        }
        if (this.en.state == true) {
            entries.en = en;
        } else {
            delete entries.en;
        }
        if (this.it.state == true) {
            entries.it = it;
        } else {
            delete entries.it;
        }
        if (this.es.state == true) {
            entries.es = es;
        } else {
            delete entries.es;
        }
        if (this.german.state == true) {
            entries.german = german;
        } else {
            delete entries.german;
        }

        return entries;
    },
},
};
</script>

Thank you for your time and help


Solution

  • v-model works both ways, so it needs to get something and to set something. You have only defined a get computed property but not a set. You use formated like it is a data property.

    So split the computed property in a get() and a set() method make this work.

    See the documentation on how this works.