0

I am trying to render a list of names using v-for. I have an array of names and I am able to create the template and render the names in the div. What I want to do is if I add any new object in my data, how can I render that part onwards of the data in a new template. So for example, everything until name 'michael' is rendered in one div, but if I add a new name to the data, from that point onwards the names should be rendered inside another template. Here is a CodePen showing my problem

new Vue({
  el: '#app',
  data() {
    return {
      myArray: [{
          name: 'Sam',
          value: 'sam'
        },
        {
          name: 'Gary',
          value: 'gary'
        },
        {
          name: 'Smith',
          value: 'smith'
        },
        {
          name: 'Sunny',
          value: 'sunny'
        },
        {
          name: 'Michael',
          value: 'michael'
        }
      ]
    }
  }
})
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <v-app id="inspire" class="ml-4">
    <template>
      <div v-for="person in myArray" key="person.name">
        {{person.name}}
      </div>
    </template>
    <template>
      //New names should be rendered here from the new values added to the data?
    </template>
  </v-app>
</div>

Any help will be appreciated. I hope I have explained my need. If not let me know.

6
  • 2
    Use two separate arrays? Commented Nov 17, 2019 at 23:42
  • I want to keep one unfortunately. I am trying to make it a bit dynamic. Commented Nov 17, 2019 at 23:43
  • 1
    Why do they need to be in the same array? You could easily merge the two arrays later if need be. Commented Nov 17, 2019 at 23:44
  • Why do you need a single array? If you need to combine them at some point, you can do so with Array.prototype.concat(). Commented Nov 17, 2019 at 23:44
  • Well i am trying to keep it one array because i would most probably be getting an array from an API call eventually. Commented Nov 17, 2019 at 23:49

2 Answers 2

0

You can do somethings like this

<template>
  ...
  <v-app id="inspire" class="ml-4">
    <template>
       <!-- Names -->
      <div v-for="person in myArray1" key="person.name">
        {{person.name}}
      </div>
    </template>
    <template>
      <!-- New names -->
      <div v-for="person in myArray2" key="person.name">
        {{person.name}}
      </div>
    </template>
    <v-btn @click="addNewPerson">
      Add
    </v-btn>
  </v-app>
  ...
</template>
<script>
export default {
  ...
  data() {
    return {
      myArray: [{
          name: 'Sam',
          value: 'sam'
        },
        {
          name: 'Gary',
          value: 'gary'
        },
        {
          name: 'Smith',
          value: 'smith'
        },
        {
          name: 'Sunny',
          value: 'sunny'
        },
        {
          name: 'Michael',
          value: 'michael'
        }
      ]
    }
  },
  computed: {
    myArray1() {
      return this.myArray.filter(it => it.recent !== true)
    },
     myArray2() {
      return this.myArray.filter(it => it.recent === true)
    },
  },
  methods: {
    addNewPerson() {
      this.myArray.push({
        name: 'Michael 1',
        value: 'michael 2',
        recent: true // add this
      })
    }
  }
  ...
}
</script>

Sign up to request clarification or add additional context in comments.

3 Comments

this is actually a really great way of doing this, however can you filter using name instead of using the true property?
How did you add a new name?
actually nevermind. i don't really need to filter by name. This will work just fine. Thank you. :D
0

To accomplish what you want, you will either need to use a computed value that returns newly added values by checking if they are in a position that exceeds the original link (or any other method really), so if you first load the component and store that the existing array has 5 elements, you can have a computed that returns the first 5 elements and put that into the first div, then another computed that returns elements 6+ into the second div. Otherwise, you will need to use two separate arrays.

Keep in mind I'm using this.$data here in the example, but the data and the values should be in the store, so it'd be this.$store.state.myArray instead.

<template>
    <div>
        <div v-for="(element, index) of getExisting" :key="index">{{element.name}}</div>
        <div v-for="(element, index) of getNew" :key="index">{{element.name}}</div>
    </div>
</template>

<script>
export default {
    data: () => ({
        created () {
            this.existing = this.myArray.length
        },
        myArray: [
            { name: 'John' },
            { name: 'James' }
        ],
        existing: null
    }),
    computed: {
        getExisting () {
            return this.$data.myArray.slice(0, this.existing)
        },
        getNew () {
            return this.$data.myArray.slice(this.existing, myArray.length)
        }
    }
}
</script>

4 Comments

this is kind of the approach i was taking but couldn't figure out how to do that so if you could provide an example that would be great. :)
Added an example.
I tried using this logic but it doesn't seem to be working: codepen.io/treehuggerrick/pen/VwwqPbQ?editors=1011. Could you please check what i am doing wrong?
Yes, the data property is set up incorrectly, so it isn't functioning. ` data: () => ({ }) ` This is a shorthand form of having a returning object. Data must be a function returning an object. For CodePen, you don't necessarily need it reactive since it's running every edit anyway for what you're doing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.