[Vuejs]-Conditional rendering inside v-for with Vue

0👍

@Rouben you need to sort how you want to set this.projects as right now in your created you assume that you’ll get the fixed array of projects back from getAllProjects.

Try doing something like this:

async getAllProjects() {
  try {
    this.isLoading = true;
    const res = await fetch(store.state.urlEndpoints.getProjects, {
      ...AuthPost(), // request config object
    });

    return await res.json().map(project => {
         project.showTags = false;
         return project;
    });

also you could try this instead inside the @click:

<b-list-group-item v-for="(project, index) in projects" :key="project.path"> 
  {{ project.name }} 
  <b-btn variant="danger" size="sm" class="list-button" @click="deleteProject(project.path)">Löschen</b-btn>
  <b-btn variant="secondary" size="sm" class="list-button" @click="openProject(project.path)">Öffnen</b-btn>
  <b-btn variant="secondary" size="sm" class="list-button" @click="flipShowTags(index, project)">Tags</b-btn>
  <search-tags v-show="project.showTags" style="margin-top: 1em;"></search-tags>
</b-list-group-item>
methods: {
  flipShowTags(index, obj) {
    this.$set(this.projects, index, {...obj, showTags: !obj.showTags})
  }
}

if it was because of it not being reactive

0👍

The problem is here…

this.projects = JSON.parse(await res.text());
this.projects.forEach((project) => { project.showTags = false; });

Adding the showTags property like this is not reactive which is why Vue doesn’t react as you expect to changes.

See Change Detection Caveats

Vue cannot detect property addition or deletion. Since Vue performs the getter/setter conversion process during instance initialization, a property must be present in the data object in order for Vue to convert it and make it reactive.

You need to have all reactive properties present when you assign the value to your projects data property. For example

export default {
  data: () => ({
    projects: [],
    isLoading: true,
    // etc
  }),
  methods: {
    async loadAllProjects () {
      try {
        this.isLoading = true;
        const res = await fetch(store.state.urlEndpoints.getProjects, {
          ...AuthPost(), // request config object
        });

        if (!res.ok) {
          throw new Error(`${res.status}: ${await res.text()}`)
        }
    
        // note that the value assigned to `this.projects` now has the
        // `showTags` property at the time of assignment
        this.projects = (await res.json()).map(project => ({
          ...project,
          showTags: false
        }))
      } catch (err) {
        this.isError = true;
      }
      this.isLoading = false
    }
  },
  created () {
    this.loadAllProjects()
  }
}

Leave a comment