VueJs not rerendering after new element is added to an array

Viewed 29

I have set a watcher to check if the dropdown value is equals to "select", if the value is equal then a new array "option" is created with one element in it. I have a button that will add a value to the array that the watcher created when the dropdown value is equal to select. The button function is working but the input field that should loop the array doesn't re-render after the button click. I am sorry I am terrible at explaining things. here is my code

<template lang="pug">
.formHolder
  .quest
    input(type="text" placeholder="Question" v-model="tempForm.tempQuestions[0].question")
    input(type="text" placeholder="Description" v-model="tempForm.tempQuestions[0].description")
    select(name="category" v-model="tempForm.tempQuestions[0].type")
      option(value="text") text
      option(value="select") Dropdown
      option(value="number") Number

this is the input field that will loop the array

    .option(v-for="(option, index) in tempForm.tempQuestions[0].options")
        input(type="text" placeholder="Option" v-model="tempForm.tempQuestions[0].options[index]")

this button adds a value to the array

    button(v-if="tempForm.tempQuestions[0].type === 'select'"  @click="addItems") Add Options   
</template>

<script>
// @ is an alias to /src
import HelloWorld from "@/components/HelloWorld.vue";

export default {
  name: "HomeView",
  components: {
    HelloWorld,
  },
  data() {
    return {
      questions: 0,
      tempForm: {
        tempQuestions: [
          {
            question: null,
            description: null,
            type: null,
          },
        ],
      },
      form: {
        questions: [],
      },
    };
  },

  methods: {
    addQuestion() {
      this.tempForm.tempQuestions.push({
        question: null,
        description: null,
        type: null,
      });
      this.questions++;
      this.readerNos++;
    },
    addOptionArray() {
      this.tempForm.tempQuestions[0].options.push("");
    },
//////// this is the function
    addItems() {
      console.log(this.tempForm.tempQuestions[0].options);
      let length = this.tempForm.tempQuestions[0].options.length;
      console.log(length);
      this.$set(this.tempForm.tempQuestions[0].options, length, "");
    },
  },
  watch: {
    tempForm: {
      handler: function () {
        this.tempForm.tempQuestions.forEach((question) => {
          if (question.type === "select") {
            question.options = [];
            question.options.push("");
          } else if (question.type === "text") {
            if (question.options) {
              delete question.options;
            }
          } else if (question.type === "number") {
            if (question.options) {
              delete question.options;
            }
          }
        });
      },
      deep: true,
    },
  },
};
</script>
1 Answers

You should use Vue.$set() when adding an empty options array - otherwise it won't be reactive and there will be no rerendering of the options in the template:

watch: 
{
    tempForm: 
    {
      handler() 
      {
        this.tempForm.tempQuestions.forEach((question) => 
        {
          if (question.type === "select") 
          {
            this.$set(question, 'options', []);
            question.options.push("");
          } 
          else if (question.type === "text") 
          {
            if (question.options) 
            {
              question.options.splice();
            }
          } 
          else if (question.type === "number") 
          {
            if (question.options) 
            {
              question.options.splice();
            }
          }
        });
      },
      deep: true,
    },
  },
Related