diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/Documentation.vue b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/Documentation.vue
index 1a70d655e00a3bc6c85f002d417497282387af7a..d787f79740d11aa9419cb9c55d0364dd87451f59 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/Documentation.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/Documentation.vue
@@ -29,6 +29,7 @@
         @open="$emit('open')"
         @loading="loading = $event"
         @save="$emit('close')"
+        @dirty="dirty = $event"
       />
       <lesson-notes v-bind="documentationPartProps" />
     </v-card-text>
@@ -45,6 +46,7 @@
         v-if="documentation.canEdit"
         @click="save"
         :loading="loading"
+        :disabled="!dirty"
       />
       <cancel-button
         v-if="!documentation.canEdit"
@@ -76,12 +78,13 @@ export default {
     SaveButton,
     CancelButton,
   },
-  emits: ["open", "close"],
+  emits: ["open", "close", "dirty"],
   mixins: [documentationPartMixin],
   data() {
     return {
       loading: false,
       documentationsMutation: createOrUpdateDocumentations,
+      dirty: false,
     };
   },
   methods: {
@@ -90,6 +93,11 @@ export default {
       this.$emit("close");
     },
   },
+  watch: {
+    dirty(dirty) {
+      this.$emit("dirty", dirty);
+    },
+  },
 };
 </script>
 
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationModal.vue b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationModal.vue
index 5b5dd101b76288cd1b09ba5418a452d70a9425fa..5508705271fe04166dc97d7937faf13e867d2351 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationModal.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/DocumentationModal.vue
@@ -1,7 +1,11 @@
 <!-- Wrapper around Documentation.vue -->
 <!-- That uses it either as list item or as editable modal dialog. -->
 <template>
-  <mobile-fullscreen-dialog v-model="popup" max-width="500px">
+  <mobile-fullscreen-dialog
+    v-model="popup"
+    max-width="500px"
+    :persistent="dirty"
+  >
     <template #activator="activator">
       <!-- list view -> activate dialog -->
       <documentation
@@ -21,6 +25,7 @@
       :absence-reasons="absenceReasons"
       :subjects="subjects"
       @close="popup = false"
+      @dirty="dirty = $event"
     />
   </mobile-fullscreen-dialog>
 </template>
@@ -38,6 +43,7 @@ export default {
   data() {
     return {
       popup: false,
+      dirty: false,
     };
   },
   props: {
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonSummary.vue b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonSummary.vue
index 3710a45f83c7d267ba281f95d2cbbaaae95f46f3..6693fa390b5ad558a198d0ca6a2d16570e239c64 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonSummary.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonSummary.vue
@@ -155,7 +155,7 @@ export default {
     documentationCacheUpdateMixin,
     documentationPartMixin,
   ],
-  emits: ["open"],
+  emits: ["open", "dirty"],
   data() {
     return {
       topic: null,
@@ -244,9 +244,25 @@ export default {
         }[this.appendIcon] || ""
       );
     },
+    dirty() {
+      return !(
+        this.topic === this.documentation.topic &&
+        this.homework === this.documentation.homework &&
+        this.groupNote === this.documentation.groupNote
+      );
+    },
   },
   mounted() {
     this.$on("save", this.handleAppendIconSuccess);
+
+    this.topic = this.documentation.topic;
+    this.homework = this.documentation.homework;
+    this.groupNote = this.documentation.groupNote;
+  },
+  watch: {
+    dirty(dirty) {
+      this.$emit("dirty", dirty);
+    },
   },
 };
 </script>