How to undo on button press?

After reading the documentation I’m not sure how to call the undo history function programmatically, for example on a button press. Thank you!

You can do…

import {undo} from "@codemirror/history"

myButton.onmousedown = e => {
  undo(view)
  e.preventDefault()
}
2 Likes

Thank you very much!

If I do this in my app I get an error:

Uncaught RangeError: Trying to update state with a transaction that doesn't start from the previous state.
    at EditorView.update (index.js:5850:23)
    at EditorView._dispatch (index.js:5776:59)
    at EditorView.dispatch (index.js:5832:14)
    at index.js:109:9
    at Proxy.undo (CodeMirror.vue:368:7)

If I hit ctrl+z everything works fine. Any idea about this? Thank you!

No. Can you show this happening in an isolated minimal script?

I had the same problem.

Uncaught RangeError: Trying to update state with a transaction that doesn't start from the previous state.
    at EditorView.update (index.js?87c0:6289:1)
    at EditorView._dispatch (index.js?87c0:6206:1)
    at EditorView.dispatch (index.js?87c0:6272:1)
    at eval (index.js?bf2b:292:1)
    at handleUndo (DataBaseSelect.vue?e041:86:1)
    at callWithErrorHandling (runtime-core.esm-bundler.js?d2dd:157:1)
    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js?d2dd:166:1)
    at SVGSVGElement.invoker (runtime-dom.esm-bundler.js?2725:345:1)
<template>
  <div>
    <button @click="handleUndo">Undo</button>
    <button @click="handleRedo">Redo</button>
  </div>
  <div class="sql-model" ref="codeRef"></div>
</template>

<script lang="ts" setup>
// "@codemirror/commands": "^6.0.0",
// "@codemirror/lang-json": "^6.0.0",
// "@codemirror/lang-sql": "^6.0.0",
// "@codemirror/state": "^6.0.0",
// "@codemirror/theme-one-dark": "^6.0.0",
// "@codemirror/view": "^6.0.0",
import { onMounted, ref } from 'vue';
import { EditorView } from '@codemirror/view';
import { basicSetup } from 'codemirror';
import { sql } from '@codemirror/lang-sql';
import { oneDark } from '@codemirror/theme-one-dark';
import { EditorState } from '@codemirror/state';
import { redo, undo } from '@codemirror/commands';

const codeRef = ref<HTMLElement>();
const view = ref<EditorView>();
const doc = ref<string>(`select t2.name, t3.service_name
FROM SI_RE_INTERFACE_DATA_SOURCE T1
         LEFT JOIN SI_DB_DATA_SOURCE T2 ON T1.DB_DATASOURCE_ID = T2.ID
         LEFT JOIN SI_SV_SERVICE_INTERFACE T3 ON T1.SV_INTERFACE_ID = T3.ID;`);

const handleUndo = () => {
  if (view.value) {
    undo({
      state: view.value.state,
      dispatch: view.value.dispatch,
    });
  }
};

const handleRedo = () => {
  if (view.value) {
    redo({
      state: view.value.state,
      dispatch: view.value.dispatch,
    });
  }
};

onMounted(() => {
  const state = EditorState.create({
    doc: doc.value,
    extensions: [
      basicSetup,
      sql(),
      oneDark,
    ],
  });

  view.value = new EditorView({
    state,
    parent: codeRef.value,
  });
});
</script>

<style scoped lang="scss">
.sql-model {
  height: 300px;
  width: 100%;
  border-top-right-radius: 4px;
  border-top-left-radius: 4px;

  :deep(.cm-editor) {
    height: 100%;

    &.cm-focused .cm-selectionBackground,
    &.cm-selectionBackground {
      background: #439AF15F;
    }
  }

  :deep(.cm-scroller) {
    overflow: auto;
  }
}
</style>

I’m not really sure why the error happend, but it seems it was due to Vue. EditorView was reactive, after I made it not reactive, everything worked again…

Thank you very much!

I implemented the editor effect in the project according to your code, but the undo and redo functions are invalid. Codemirror is the same version


Cancel and redo error reporting

Did you read the comment above? Make sure you’re not wrapping the editor state in a reactive proxy if you’re using Vue.

Uploading: 1682316569496.png…
I’m the same way as it actually is, but I don’t know why marketing and re-doing didn’t work

I am using the Vue implementation method and also using ref instead of using reactive

I got the same problem in vue, and finally solved it using “shallowRef”.