kundefine's avatar

assign same value in the Vue data doesn't change in the dom

i want to change or reflect in the dom when i assign same value in the Vue data. I am really bad at explaining, sorry for that. please check the comment for more details.

<div id="app">
    <div>
        <span 
        contenteditable="true" 
        v-text="setting.change_setting_value === null ? setting.setting_default_value : setting.change_setting_value"
        @blur="changeSetting"
        >
    </span>
    </div>
</div>

const app = new Vue({
el: "#app",
data: {
    setting_default_value: "default value",
    change_setting_value: null
},
method: {
    changeSetting(evt) {
        if(evt.target.innerText === "") {
// dosen't change in the dom because setting_default_value never change its is the same value as before 
// now i want to know how can i change back the contenteditable span when i assign the same value
// i don't want to touch the dom 
            this.setting.setting_default_value = "default value" // not reflect in the dom what i can do to change the effect

// if i change the default value something else it will change in the dom in this case its the span element
            this.setting.setting_default_value = "change value" // reflect in the dom
        } else {
            this.setting.change_setting_value = "setting value has been change"
        }
    }
}
});
0 likes
8 replies
piljac1's avatar

Not sure what you're trying to accomplish exactly, but two things are wrong with your code :

  1. Your method key should be called methods
  2. You're accessing and setting setting.change_setting_value and setting.setting_default_value while setting is not defined in your data properties.

A fixed version of what you posted would be :

const app = new Vue({
el: "#app",
data: {
    setting: {
        setting_default_value: "default value",
        change_setting_value: null
    }
},
methods: {
    changeSetting(evt) {
        if(evt.target.innerText === "") {
// dosen't change in the dom because setting_default_value never change its is the same value as before 
// now i want to know how can i change back the contenteditable span when i assign the same value
// i don't want to touch the dom 
            this.setting.setting_default_value = "default value" // not reflect in the dom what i can do to change the effect

// if i change the default value something else it will change in the dom in this case its the span element
            this.setting.setting_default_value = "change value" // reflect in the dom
        } else {
            this.setting.change_setting_value = "setting value has been change"
        }
    }
}
});

Now, as I said, I didn't understand what was the expected behavior, but with these fixes you'll get something functional.

karlos545's avatar

To add to what @piljac1 mentioned.

I'm pretty sure that you will need to return an object in your data.

data() {
    return {
        setting_default_value: "default value",
        change_setting_value: null
    }
},```
piljac1's avatar

@karlos545 His example uses the main VM, so you need to use data as an object key and not a function. In components, you need to use it as a function with a return statement as you posted.

1 like
kundefine's avatar

by default in the view i want to show the default setting if the setting is null. if the user change the default setting and setting_value is valid then it will show the setting value in the contenteditable span. but if the setting value is invalid it will show the default value again.

here is the response can be

{
created_at: null
id: 1
// currently has the default value in the span and response setting_value is null and setting_default_value is the same as before that why when i assign with response value to the data its doesn't detect the change and doesn't change the span with the setting_default_value.
setting_default_value: "10,5,1" 
setting_name: "User Registration Bonus"
setting_value: null // setting value doesn't change
updated_at: "2020-07-27T06:21:22.000000Z"
},
{
created_at: null
id: 1
setting_default_value: "10,5,1"
setting_name: "User Registration Bonus"
setting_value: "20,30,40" // setting value change and also change in the view
updated_at: "2020-07-27T06:21:22.000000Z"
}

<tr v-if="settings.length > 0" v-for="setting in settings">
    <td class="font-weight-bold">
        @{{ setting.setting_name }}
    </td>

    <td class="vertical-align-middle">
        <span
            contenteditable="true"
            class="mr-5 admin-change-setting"
            v-bind:name="setting.setting_name"
            @blur="changeAdminSettings"
            v-text="setting.setting_value !== null ? setting.setting_value : setting.setting_default_value"
        >
        </span>
        <i class="fa fa-pencil pull-right"></i>
    </td>
</tr>                      	
asettings = new Vue({
    el: '#adminSettings',
    data: {
        settings: [{
            created_at: null
            id: 1
            setting_default_value: "10,5,1"
            setting_name: "User Registration Bonus"
            setting_value: null
            updated_at: "2020-07-27T06:21:22.000000Z"
        }]
    },
    methods: {
        changeAdminSettings  (evt) {
            let settingName = evt.target.getAttribute('name');
            let settingValue = evt.target.innerText;
            axios({
                method: 'patch',
                url: window.settingUpdateUrl,
                data: {
                    settingName,
                    settingValue
                }
            }).then(response => {
                for (let i = 0; i < this.settings.length; i++) {
                    if(this.settings[i].setting_name === response.data.setting_name) {
                        this.settings[i].setting_value = response.data.setting_value;
                        this.settings[i].setting_default_value = response.data.setting_default_value;
                        
                          if(this.settings[i].setting_value === null) {
                            // over here i have to modify the DOM manually because the response setting_default_value data is same that's why its doesn't detect the change in the and never update the view
                            evt.target.innerText = response.data.setting_default_value;
                        }
                    }
                }
            });

        }
    }
});
piljac1's avatar

It's never a good idea to modify the DOM directly when working with Vue. What you could do, is use this.$set on your current index and reassign the exact same object. That way, it will always trigger an update.

for (let i = 0; i < this.settings.length; i++) {
    if(this.settings[i].setting_name === response.data.setting_name) {
        this.settings[i].setting_value = response.data.setting_value;
        this.settings[i].setting_default_value = response.data.setting_default_value;
        this.$set(this.settings, i, this.settings[i]);
    }
}
kundefine's avatar

doesn't trigger an update. the same problem, the same value doesn't update

piljac1's avatar

I don't know what's wrong on your side, but before posting my previous comment, I tested the behavior on CodePen. I just reproduced it and saved it for you.

https://codepen.io/jacob-pilon/pen/VweJWmM

Of course, you can see that I'm not using an Axios call, but I'm basically always reassigning the same values when changeAdminSettings is called. I set a watcher on the settings array which triggers an alert when updated. I did the same for the updated hook. Both ALWAYS get called when you focus out of the span (blur), which means an update is indeed caught and that the content has been re-rendered.

Please or to participate in this conversation.