0

I have a simple application where a user selects a value from a dropdown list and when they click on the "add" button that value and its id should be populated into an array using the id as an index.

Example:

Values


1 - Apple
3 - Bananas 8 - Pears

User selects each fruit, clicking add after each selection. My array should look like this:

 [
    1: Apple,
    3: Bananas,
    8: Pears
 ]

However what I end up with in Vue is this:

[
    1: Apple,
    2: undefined,
    3: Bananas,
    4: undefined,
    5: undefined,
    6: undefined,
    7: undefined,
    8: Pears
]

These values are being passed as input to server validation and obviously this is creating a problem with array length and validation rules. How can I remove these undefined values or prevent Vue from populating them in the first place?

3
  • 1
    how does your array have key and value pairs Commented Feb 2, 2019 at 21:35
  • I'm assigning it with this.array[index] = fruit; Commented Feb 2, 2019 at 22:30
  • 1
    then it is going to assign undefined since the indexes in between are not assigned a value. since you are assigning only for indexes 1,2,8. Cant you use object or Map instead? Commented Feb 2, 2019 at 22:51

2 Answers 2

2

Vue isn't inserting undefined into your array. That's just the behavior of JavaScript arrays (i.e., sparse arrays).

A quick solution to get a new array of the defined elements is to use Array.prototype.filter:

const input = [
  'Apple',
  undefined,
  'Bananas',
  undefined,
  undefined,
  undefined,
  undefined,
  'Pears'
];
const output = input.filter(x => x); // filter out undefined elements
console.log(output)

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

Comments

0

Arrays are always contiguous; any "holes" in the array will be filled with undefined.

What you want to use instead is an object:

{
  data() {
    return {
      items: {}
    }
  },

  methods: {
    add(id, item) {
      // Vue cannot detect property additions, so we must use
      // this method to do so
      this.$set(this.items, id, item)
    }
  }
}

If you render out the items of this object in the template with v-for, the order will typically be the same as the order in which each item was added to the object (see v-for with an Object). If you require the items to be rendered in ID order, then you need to sort the items:

<div v-for="item of itemsArray">{{ item }}</div>
computed: {
  itemsArray() {
    return Object.entries(this.items)
      .sort((a, b) => a[0] - b[0])  // sort entry key (ID)
      .map(a => a[1])  // take entry value
  }
}

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.