[Vuejs]-Change ordering of a array of objects with up/down buttons

2👍

Interesting challenge. Using my Vue 2 CLI sandbox app, I came up with functionality that doesn’t require an ‘order’ property. Here is the component code:

<template>
  <div class="swap-array-objects">
    <h3>SwapArrayObjects.vue</h3>
    <div class="row">
      <div class="col-md-6">
        <table class="table table-bordered">
          <thead>
            <tr>
              <th>TITLE</th>
              <th>&nbsp;</th>
              <th>&nbsp;</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="(item, index) in items" :key="index">
              <td>{{ item.title }}</td>
              <td>
                <button class="btn btn-secondary btn-sm" @click="moveUp(index)">Up</button>
              </td>
              <td>
                <button class="btn btn-secondary btn-sm" @click="moveDown(index)">Down</button>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        items: [
          {
            title: 'title1'
          },
          {
            title: 'title2'
          },
          {
            title: 'title3'
          },
          {
            title: 'title4'
          },
          {
            title: 'title5'
          }
        ]
      }
    },
    methods: {
      moveUp(index) {
        if (index === 0) {
          return;
        }

        let priorIndex = index - 1;

        let itemCopy = {...this.items[index]};
        let priorItemCopy = {...this.items[priorIndex]};

        // Swap array position with prior element
        this.$set(this.items, priorIndex, itemCopy);
        this.$set(this.items, index, priorItemCopy);
      },
      moveDown(index) {
        if (index === this.items.length - 1) {
          return;
        }

        let subsequentIndex = index + 1;

        let itemCopy = {...this.items[index]};
        let subsequentItemCopy = {...this.items[subsequentIndex]};

        // Swap array positions with subsequent element
        this.$set(this.items, subsequentIndex, itemCopy);
        this.$set(this.items, index, subsequentItemCopy);
      }
    }
  }
</script>
👤Tim

1👍

This solution is similar to Tim’s, but a bit simpler and easier to follow:

<template>
  <v-app>
    <ul>
      <li v-for="(item, index) in items" :key="index">
        {{item.order}} {{item.title}} {{index}} 
        <button @click="changeOrderDown(item, index)" v-if="index != items.length-1">down</button>
        <button @click="changeOrderUp(item, index)" v-if="index != 0">up</button>
      </li>
    </ul>
  </v-app>
</template>

<script>

export default {
  name: 'App',
  data: () => ({
    items: [
      {
        title: "test1", 
        order: 1
      },
      {
        title: "test2", 
        order: 2
      },
      {
        title: "test3", 
        order: 3
      }
    ]
  }),
  methods: {
    changeOrderDown(item, index) {
      // save clicked item in temporary variable
      let temp = item
      // move the following item to the clicked element
      this.items[index] = this.items[index + 1]
      // move clicked item to destination 
      this.items[index + 1] = temp
    },
     changeOrderUp(item, index) {
       // save clicked item in temporary variable
      let temp = item
      // move the following item to the clicked element
      this.items[index] = this.items[index - 1]
      // move clicked item to destination 
      this.items[index - 1] = temp      
    },
  }
};
</script>
<template>
  <v-app>
    <ul>
      <li v-for="(item, index) in items" :key="index">
        {{item.order}} {{item.title}} {{index}} 
        <button @click="changeOrderDown(item, index)" v-if="index != items.length-1">down</button>
        <button @click="changeOrderUp(item, index)" v-if="index != 0">up</button>
      </li>
    </ul>
  </v-app>
</template>

<script>

export default {
  name: 'App',
  data: () => ({
    items: [
      {
        title: "test1", 
        order: 1
      },
      {
        title: "test2", 
        order: 2
      },
      {
        title: "test3", 
        order: 3
      }
    ]
  }),
  methods: {
    changeOrderDown(item, index) {
      // save clicked item in temporary variable
      let temp = item
      // move the following item to the clicked element
      this.items[index] = this.items[index + 1]
      // move clicked item to destination 
      this.items[index + 1] = temp
    },
     changeOrderUp(item, index) {
       // save clicked item in temporary variable
      let temp = item
      // move the following item to the clicked element
      this.items[index] = this.items[index - 1]
      // move clicked item to destination 
      this.items[index - 1] = temp      
    },
  }
};
</script>

Leave a comment