diff --git a/src/components/Dataset/RemoveModal.vue b/src/components/Dataset/RemoveModal.vue
index 8e7c50b00b6a540e5606b97dc207bd06d45eb8d7..1ba157d8661525e148a20386c5e6e330d8559433 100644
--- a/src/components/Dataset/RemoveModal.vue
+++ b/src/components/Dataset/RemoveModal.vue
@@ -33,7 +33,7 @@ import Modal from '@/components/Modal.vue'
 import { mapActions, mapState } from 'pinia'
 import { useDatasetStore, useNotificationStore } from '@/stores'
 import { Dataset } from '@/types/dataset'
-import { ElementList } from '@/types'
+import { ElementList, Element } from '@/types'
 
 export default defineComponent({
   components: {
@@ -49,7 +49,7 @@ export default defineComponent({
   props: {
     // The element to delete.
     element: {
-      type: Object as PropType<ElementList>,
+      type: Object as PropType<ElementList | Element>,
       required: true
     },
     dataset: {
@@ -66,7 +66,6 @@ export default defineComponent({
     }
   },
   data: () => ({
-    opened: false,
     loading: false
   }),
   computed: {
@@ -88,15 +87,12 @@ export default defineComponent({
     ...mapActions(useDatasetStore, ['removeDatasetElement']),
     ...mapActions(useNotificationStore, ['notify']),
     updateModelValue (value: boolean) { this.$emit('update:modelValue', value) },
-    open () {
-      this.opened = this.canRemove
-    },
     async performRemove () {
       if (!this.canRemove) return
       this.loading = true
       try {
         await this.removeDatasetElement(this.dataset.id, this.element.id, this.set)
-        this.opened = false
+        this.updateModelValue(false)
       } finally {
         this.loading = false
       }
diff --git a/src/components/Element/Datasets/ElementDatasets.vue b/src/components/Element/Datasets/ElementDatasets.vue
new file mode 100644
index 0000000000000000000000000000000000000000..5dbdac806fdd5b6a3e253a75ed899e0e0aa92cb1
--- /dev/null
+++ b/src/components/Element/Datasets/ElementDatasets.vue
@@ -0,0 +1,54 @@
+<template>
+  <div class="loader m-auto is-size-3" v-if="datasets === null"></div>
+  <div class="message-body has-text-grey" v-else-if="datasets.length === 0">
+    No datasets
+  </div>
+  <table v-else class="table is-fullwidth is-hoverable">
+    <thead>
+      <th>Name</th>
+      <th>Set</th>
+      <th></th>
+    </thead>
+    <tbody>
+      <tr v-for="({ dataset, set }) in datasets" :key="dataset.id + set">
+        <Row
+          :corpus-id="corpusId"
+          :dataset="dataset"
+          :set="set"
+          :element="element"
+        />
+      </tr>
+    </tbody>
+  </table>
+</template>
+
+<script lang="ts">
+import { defineComponent, PropType } from 'vue'
+import { ElementDataset } from '@/types/dataset'
+import { mapState } from 'pinia'
+import { useElementsStore } from '@/stores'
+import { Element } from '@/types'
+import Row from './Row.vue'
+
+export default defineComponent({
+  components: {
+    Row
+  },
+  props: {
+    corpusId: {
+      type: String,
+      required: true
+    },
+    element: {
+      type: Object as PropType<Element>,
+      required: true
+    }
+  },
+  computed: {
+    ...mapState(useElementsStore, ['elementDatasets']),
+    datasets (): ElementDataset[] | null {
+      return this.elementDatasets?.[this.element.id] ?? null
+    }
+  }
+})
+</script>
diff --git a/src/components/Element/Datasets/Row.vue b/src/components/Element/Datasets/Row.vue
new file mode 100644
index 0000000000000000000000000000000000000000..5391a3956f9f49229c8119adb786c670f4539a20
--- /dev/null
+++ b/src/components/Element/Datasets/Row.vue
@@ -0,0 +1,84 @@
+<template>
+  <td>
+    <router-link :to="{ name: 'dataset-details', params: { datasetId: dataset.id } }" title="Dataset details">
+      {{ dataset.name }}
+    </router-link>
+  </td>
+  <td>{{ set }}</td>
+  <td>
+    <a
+      :title="title"
+      class="icon is-pulled-right"
+      v-on:click="removeElement"
+    >
+      <i class="icon-remove-square" :class="canRemove ? 'has-text-danger' : 'has-text-grey'" type="button"></i>
+    </a>
+  </td>
+  <RemoveModal
+    v-if="dataset && set"
+    v-model="removeElementModal"
+    :dataset="dataset"
+    :set="set"
+    :element="element"
+  />
+</template>
+
+<script lang="ts">
+import { corporaMixin } from '@/mixins'
+import { defineComponent, PropType } from 'vue'
+import { Dataset, ElementDataset } from '@/types/dataset'
+import { mapState } from 'pinia'
+import { useElementsStore } from '@/stores'
+import RemoveModal from '@/components/Dataset/RemoveModal.vue'
+import { Element } from '@/types'
+
+export default defineComponent({
+  mixins: [
+    corporaMixin
+  ],
+  components: {
+    RemoveModal
+  },
+  props: {
+    corpusId: {
+      type: String,
+      required: true
+    },
+    element: {
+      type: Object as PropType<Element>,
+      required: true
+    },
+    dataset: {
+      type: Object as PropType<Dataset>,
+      required: true
+    },
+    set: {
+      type: String,
+      required: true
+    }
+  },
+  data: () => ({
+    removeElementModal: false
+  }),
+  computed: {
+    ...mapState(useElementsStore, ['elementDatasets']),
+    datasets (): ElementDataset[] | null {
+      return this.elementDatasets?.[this.element.id] ?? null
+    },
+    canRemove () {
+      return (this.dataset && this.dataset.state === 'open' && this.set && this.canWrite(this.corpus))
+    },
+    title () {
+      if (!this.canWrite(this.corpus)) return 'You do not have the required rights to edit this dataset'
+      else if (this.dataset.state !== 'open') return 'Only open datasets can be edited'
+      else return 'Remove element from this dataset'
+    }
+  },
+  methods: {
+    removeElement () {
+      if (!this.canRemove) return
+      this.removeElementModal = true
+    }
+  }
+})
+</script>
diff --git a/src/components/Element/DeleteModal.vue b/src/components/Element/DeleteModal.vue
index c3e34213bfe3763b10acaa85088beea761c5189f..c724126ad13ebd4fb293d2fd0bfd16e484fe2a17 100644
--- a/src/components/Element/DeleteModal.vue
+++ b/src/components/Element/DeleteModal.vue
@@ -9,7 +9,7 @@
     <slot :open="open" :can-delete="canDelete">
       <i
         class="icon-trash"
-        :class="canDelete ? 'has-text-danger' : 'has-text-gray'"
+        :class="canDelete ? 'has-text-danger' : 'has-text-grey'"
         v-on:click.prevent="open"
       ></i>
     </slot>
diff --git a/src/components/Element/DetailsPanel.vue b/src/components/Element/DetailsPanel.vue
index 56fc5542be37ef72352085d06f754f4691079e72..5da09f6974e79dfaaa34aae6f6edc47d1fe62dbe 100644
--- a/src/components/Element/DetailsPanel.vue
+++ b/src/components/Element/DetailsPanel.vue
@@ -64,30 +64,7 @@
       <hr />
 
       <DropdownContent id="datasets" title="Datasets">
-        <div class="loader m-auto is-size-3" v-if="datasets === null">
-        </div>
-        <div class="message-body has-text-grey" v-else-if="datasets.length === 0">
-          No datasets
-        </div>
-        <table v-else class="table is-fullwidth is-hoverable">
-          <thead>
-            <th>Name</th>
-            <th>Set</th>
-          </thead>
-          <tbody>
-            <tr v-for="({ dataset, set }) in datasets" :key="dataset.id + set">
-              <td>
-                <router-link
-                  :to="{ name: 'dataset-details', params: { datasetId: dataset.id } }"
-                  title="Dataset details"
-                >
-                  {{ dataset.name }}
-                </router-link>
-              </td>
-              <td>{{ set }}</td>
-            </tr>
-          </tbody>
-        </table>
+        <ElementDatasets :corpus-id="corpusId" :element="element" />
       </DropdownContent>
 
       <EntityLinks
@@ -121,6 +98,7 @@ import OrientationPanel from '@/components/Element/OrientationPanel.vue'
 import Transcriptions from '@/components/Element/Transcription'
 import TranscriptionsModal from '@/components/Element/Transcription/Modal.vue'
 import TranscriptionCreationForm from '@/components/Element/Transcription/CreationForm.vue'
+import ElementDatasets from '@/components/Element/Datasets/ElementDatasets.vue'
 
 export default defineComponent({
   mixins: [
@@ -135,7 +113,8 @@ export default defineComponent({
     OrientationPanel,
     TranscriptionCreationForm,
     Transcriptions,
-    TranscriptionsModal
+    TranscriptionsModal,
+    ElementDatasets
   },
   props: {
     /**
diff --git a/src/stores/dataset.ts b/src/stores/dataset.ts
index 9bf37836fdd2365327a774087fa37fb362e77a46..d9f3956380abc6820697a9d98a404f63af165cea 100644
--- a/src/stores/dataset.ts
+++ b/src/stores/dataset.ts
@@ -18,6 +18,7 @@ import {
   updateDataset
 } from '@/api'
 import { errorParser } from '@/helpers'
+import { useElementsStore } from './elements'
 
 interface State {
   /**
@@ -155,9 +156,17 @@ export const useDatasetStore = defineStore('dataset', {
     async removeDatasetElement (datasetId: UUID, elementId: UUID, set: string) {
       try {
         await deleteDatasetElement(datasetId, elementId, set)
-        const index = this.datasetElements[datasetId].findIndex(datasetElement => datasetElement.set === set && datasetElement.element.id === elementId)
-        if (index < 0) throw new Error(`Element ${elementId} not found in set ${set} of dataset ${datasetId}`)
-        this.datasetElements[datasetId].splice(index, 1)
+        if (this.datasetElements[datasetId]) {
+          const index = this.datasetElements[datasetId].findIndex(datasetElement => datasetElement.set === set && datasetElement.element.id === elementId)
+          if (index < 0) throw new Error(`Element ${elementId} not found in set ${set} of dataset ${datasetId}`)
+          this.datasetElements[datasetId].splice(index, 1)
+        }
+        const elementDatasets = useElementsStore().elementDatasets[elementId]
+        if (elementDatasets) {
+          const index = elementDatasets.findIndex(dataset => dataset.dataset.id === datasetId && dataset.set === set)
+          if (index < 0) throw new Error(`Dataset ${elementId} not found in set ${set} of dataset ${datasetId}`)
+          elementDatasets.splice(index, 1)
+        }
       } catch (err) {
         useNotificationStore().notify({ type: 'error', text: errorParser(err) })
         throw err
diff --git a/tests/unit/stores/datasets.spec.js b/tests/unit/stores/datasets.spec.js
index f13163bfb16422b9e0f8a805bc8a730e90545e0c..ba705f99d99e0be9207b986c5673e68725d2c5b7 100644
--- a/tests/unit/stores/datasets.spec.js
+++ b/tests/unit/stores/datasets.spec.js
@@ -1,17 +1,18 @@
 import { assert } from 'chai'
 import axios from 'axios'
 import { FakeAxios, assertRejects, setUpTestPinia, actionsCompletedPlugin } from '../testhelpers'
-import { useDatasetStore, useNotificationStore } from '@/stores'
+import { useDatasetStore, useElementsStore, useNotificationStore } from '@/stores'
 
 describe('datasets', () => {
   describe('actions', () => {
-    let mock, store, notificationStore
+    let mock, store, notificationStore, elementsStore
 
     before('Setting up mocks', () => {
       mock = new FakeAxios(axios)
       setUpTestPinia([actionsCompletedPlugin])
       store = useDatasetStore()
       notificationStore = useNotificationStore()
+      elementsStore = useElementsStore()
     })
 
     afterEach(() => {
@@ -19,6 +20,7 @@ describe('datasets', () => {
       mock.reset()
       store.$reset()
       notificationStore.$reset()
+      elementsStore.$reset()
     })
 
     after('Removing Axios mock', () => {
@@ -690,6 +692,20 @@ describe('datasets', () => {
         store.datasetElements = {
           'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa': elements
         }
+        elementsStore.elementDatasets = {
+          2: [
+            {
+              set: 'unit-01',
+              dataset: {
+                id: 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
+                state: 'open',
+                name: 'Shin Seiki Evangelion',
+                description: 'Become legend, young boy!',
+                sets: ['unit-00', 'unit-01', 'unit-02']
+              }
+            }
+          ]
+        }
 
         mock.onDelete('/datasets/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa/elements/2/', 'unit-01').reply(204)
 
@@ -738,6 +754,9 @@ describe('datasets', () => {
             }
           ]
         })
+        assert.deepStrictEqual(elementsStore.elementDatasets, {
+          2: []
+        })
       })
 
       it('handles errors', async () => {