sy-huss
sy-huss

Reputation: 193

Parent component updates a child component v-for list, the new list is not rendered in the viewport (vue.js)

My app structure is as follows. The Parent app has an editable form, with a child component list placed at the side. The child component is a list of students in a table.

I'm trying to update a child component list. The child component uses a 'v-for', the list is generated through a web service call using Axios.

In my parent component, I am editing a students name, but the students new name is not reflected in the List that I have on screen.

Example:

Parent/Child Component

Notice on the left the parent form has the updated name now stored in the DB. However, the list (child component) remains unchanged.

I have tried a few things such as using props, ref etc. I am starting to think that my app architecture may be incorrect.

Does anyone know how I might go about solving this issue.

Sections of the code below. You may understand that I am a novice at Vue.

Assistance much appreciated.

// Child component
<component>
..
   <tr v-for="student in Students.slice().reverse()" :key="student._id">
..
</component>

export default {
    env: '',
    // list: this.Students,
    props: {
        inputData: Boolean,
    },
    data() {
        return {
            Students: [],
        };
    },
    created() {
    
    // AXIOS web call...
    
    },
};


// Parent component
import List from "./components/students/listTerms";

export default {
  name: "App",
  components: {
    Header,
    Footer,
    List,
  },
};

// Implementation
 <List />

Upvotes: 1

Views: 693

Answers (2)

Lenkors Wood
Lenkors Wood

Reputation: 25

I think that it is better to use vuex for this case and make changes with mutations. Because when you change an object in the data array, it is not overwritten. reactivity doesn't work that way read more about it here

Upvotes: 1

Dan Knights
Dan Knights

Reputation: 8378

If your list component doesn't make a fresh API call each time the form is submitted, the data won't reflect the changes. However, making a separate request each time doesn't make much sense when the component is a child of the form component.

To utilise Vue's reactivity and prevent overhead, it would be best to use props.

As a simplified example:

// Child component
<template>
...
  <tr v-for="student in [...students].reverse()" :key="student._id">
...
</template>

<script>
export default {
  props: {
    students: Array,
  },
};
</script>

// Parent component
<template>
  <div>
    <form @submit.prevent="submitForm">
      <input v-model="studentData.name" />
      <input type="submit" value="SUBMIT" />
    </form>
    <List :students="students" />
  </div>
</template>

<script>
import List from "./components/students/listTerms";

export default {
  name: "App",
  components: {
    List,
  },
  data() {
    return {
      students: [],
      studentData: {
        name: ''
      }
    }
  },
  methods: {
    submitForm() {
      this.$axios.post('/endpoint', this.studentData).then(() => {
        this.students.push({ ...this.studentData });
      }).catch(err => {
        console.error(err)
      })
    }
  }
};
</script>

Working example.

This ensures data that isn't stored successfully won't be displayed and data that is stored successfully reflects in the child component.

Upvotes: 0

Related Questions