1

My table is not updating while I'm removing one of its element.

My Vue page:

<template>
    <div class="home">
        <div class="py-10">

            <header>
                <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
                <h1 class="text-3xl font-bold leading-tight text-gray-900">Items</h1>
                </div>
            </header>
            <main>
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
          <div class="flex flex-col">
            <div class="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
                <div class="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
                    <div class="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
                    <table class="min-w-full divide-y divide-gray-200">
                        <thead class="bg-gray-50">
                        <tr>
                            <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                                Name
                            </th>
                            <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                                Hostname
                            </th>
                            <th scope="col" class="relative px-6 py-3">
                                <span class="sr-only">Actions</span>
                            </th>
                        </tr>
                        </thead>
                        <tbody>
                            <tr v-for="(item, index) in items.value" :key="index" :class="index % 2 === 0 ? 'bg-white' : 'bg-gray-50'">
                                <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{{ item._source.name }}</td>
                                <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ item._source.hostname }}</td>
                                <td class="px-6 py-4 whitespace-nowrap text-right text-sm">
                                    <div class="flex flex-row-reverse">
                                        <div @click="deleteItem(item._id)" class="px-1 text-red-600 hover:text-red-900">
                                            <TrashIcon class="h-5 w-5"/>
                                        </div>
                                    </div>
                                </td>
                            </tr>
                        </tbody>
                        
                </table>
                </div>
            </div>
            </div>
        </div>
        </div>
      </main>

        </div>
    </div>
</template>

<script>
import { ref } from '@vue/reactivity'
import { TrashIcon } from '@heroicons/vue/outline'
import ItemsService from '../../services/items.service'
export default {
    name: 'ReadItems',
    components: {
        TrashIcon,
    },
    data(){
        return {
            items: ref([]),
        }
    },

    async mounted(){
        this.items.value = await this.readItems()
    },

    methods: {
        async readItems(){
            let temp = null
            try {
                temp = await ItemsService.readItems()
                temp = temp.data.body.hits.hits
            } catch (error) {
                console.log('Error: could not retrieve all items.')
            }
            return temp
        },

        async deleteItem(itemId){
            await ItemsService.deleteItem({ _id: itemId })
            await this.readItems()
        }
    }
}
</script>

When I run the deleteItem method, I need to reload page to see the item disappeared. I would like to see it without having to reload the page...

1 Answer 1

1

Don't use ref from composition API in data function in options API, here the data is already reactive :

const app = Vue.createApp({
  data() {
    return {
      items: [],
    };
  },
  async mounted(){
    this.items = await this.readItems()
  },
  methods: {
    async readItems(){
      let temp = null
      try {
        // setTimeout emulates async call
        setTimeout(() => this.items = [{_id: '1', _source: {name: 'aaa', hostname: 'aaa'}}, {_id: '2', _source: {name: 'bbb', hostname: 'bbb'}}, {_id: '3', _source: {name: 'ccc', hostname: 'ccc'}}], 2000)
        //temp = await ItemsService.readItems()
        //temp = temp.data.body.hits.hits
      } catch (error) {
        console.log('Error: could not retrieve all items.')
      }
      return temp
    },
    async deleteItem(itemId){
      // setTimeout emulates async call
      setTimeout(() => this.items = this.items.filter(i => i._id !== itemId), 1000)
      //await ItemsService.deleteItem({ _id: itemId })
    }
  }
})
app.mount('#demo')
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" integrity="sha512-wnea99uKIC3TJF7v4eKk4Y+lMz2Mklv18+r4na2Gn1abDRPPOeef95xTzdwGD9e6zXJBteMIhZ1+68QC5byJZw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://unpkg.com/vue@next"></script>
<div id="demo">
  <div class="home">
    <div class="py-10">
      <header>
        <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
          <h1 class="text-3xl font-bold leading-tight text-gray-900">Items</h1>
        </div>
      </header>
      <main>
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
          <div class="flex flex-col">
            <div class="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
              <div class="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
                <div class="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
                  <table class="min-w-full divide-y divide-gray-200">
                    <thead class="bg-gray-50">
                      <tr>
                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                          Name
                        </th>
                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                          Hostname
                        </th>
                        <th scope="col" class="relative px-6 py-3">
                          <span class="sr-only">Actions</span>
                        </th>
                      </tr>
                    </thead>
                      <tbody>
                        <tr v-for="(item, index) in items" :key="index" :class="index % 2 === 0 ? 'bg-white' : 'bg-gray-50'">
                          <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{{ item._source.name }}</td>
                          <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ item._source.hostname }}</td>
                          <td class="px-6 py-4 whitespace-nowrap text-right text-sm">
                            <div class="flex flex-row-reverse">
                              <div @click="deleteItem(item._id)" class="px-1 text-red-600 hover:text-red-900 cursor-pointer">
                                <!--<TrashIcon class="h-5 w-5"/>-->
                                delete
                              </div>
                            </div>
                          </td>
                        </tr>
                     </tbody>
                  </table>
                </div>
              </div>
            </div>
          </div>
        </div>
      </main>
    </div>
  </div>
</div>

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

2 Comments

Thanks for the solution. Does it mean that for this kind of process, I always need to run a "parallel" script filtering (in this case) the array ?
@Henri hey mate, no you can skip filtering for local items and instead after deleting just call this.readItems()

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.