Home > database >  Vue: Radio does not update its value when data changes asynchronously
Vue: Radio does not update its value when data changes asynchronously

Time:10-04

I do not understand why my new code does not work. I was able to extract a minimum reproducible case. When the created() sets a data synchronously, it works well and an article radio is displayed. When I surround it with timeout, then the blog stays selected. Vue 2.6.12

The bug in this code has been fixed, but this was not the cause for my troubles because my real code is different. My problem is that the radio button is not checked when it should be after the reactive data is changed.

<Radio
  v-model="type"
  identifier="article"
  class="pl-3"
  label="article"
  name="type"
/>
<Radio
  v-model="type"
  identifier="blog"
  class="pl-3"
  label="blog"
  name="type"
/>
<div>Selected {{ type }}</div>

  data() {
    return {
      type: "blog",
    };
  },
  created() {
    setTimeout(function () {
      this.type = "article";
      console.log(this.type);
    }, 800);
  },

This makes my head explode because a similar code in different component works well.

UPDATE:

my original code, that does not work, is

computed: {
  blog() {
    return this.$store.getters.BLOG;
  },
},
watch: {
 blog() {
  this.type = (this.blog.info.editorial) ? 'article' : 'blog';
 },

created() {
  this.$store.dispatch('FETCH_BLOG', { slug: this.slug });
},

Relevant source code:

CodePudding user response:

All you need is to change your function to an arrow function because it isn't point your data like this

setTimeout(() => {
      this.type = "article";
      console.log(this.type);
}, 800);

CodePudding user response:

I assume your original code does not set the type in vue's data function, so it will not reactive when you assign this.type to a new value.

Manage state in a form is complicated, check out this library: https://github.com/vue-formily/formily and maybe it helps you easier to work with form, it will let you separate the form definition from vue component that makes it reusable, and it will manage the state for you...

Here is a small demo for your problem: https://codepen.io/hqnan/pen/YzQbxxo

CodePudding user response:

The problem is the selected property in Radio.vue is only set equal to value in the created() hook. When the setTimeout() occurs in the parent component, Radio.vue's v-model property is changed, which updates its value property, but its selected property is not automatically updated to match.

The solution is to replace the created() hook change with a watcher on value that updates selected:

// Radio.vue
export default {
  created() {
    // ⛔️ Remove this
    //if (this.value) {
    //  this.selected = this.value
    //}
  },

  watch: {
    value: {
      handler(value) {
        this.selected = value
      },
      immediate: true,
    },
  },
}

demo

  • Related