Example of onchange for CodeMirror6?

I could not figure out which API(s) in view/state to listen on state.doc change.

1 Like

I think this is the closest equivalent to CM5’s change event:

let updateListenerExtension = EditorView.updateListener.of((update) => {
  if (update.docChanged) {
    // Handle the event here
  }
});

let state = EditorState.create({
    extensions: [updateListenerExtension/* Add your other extensions */]
});
5 Likes

Is there a way to add a listener to already existing state?

Without importing global variables EditorView and EditorState, which might be from a different version package. And without creating a new state, because the existing state might have a number of extensions attached.

Something like this:

const dispatch = editor.dispatch;
editor.dispatch = (...args: any[]) => {
  console.log('update xxx');
  return dispatch.apply(editor, args);
};

I ended with something like this:

  private _d?: (...args: any[]) => unknown;

  constructor(protected readonly editor: EditorView) {
    this._d = editor.dispatch;
    Object.defineProperty(editor, 'dispatch', {
      ...Object.getOwnPropertyDescriptor(editor, 'dispatch'),
      value: (...args: any[]) => {
        const res = this._d!.apply(editor, args);
        this.onchange?.();
        return res;
      },
    });
  }

  public dispose(): void {
    if (this._d) {
      Object.defineProperty(this.editor, 'dispatch', {
        ...Object.getOwnPropertyDescriptor(this.editor, 'dispatch'),
        value: this._d,
      });
    }
  }

let view = new EditorView({
doc: “//Type here\na=10; \n b”,
extensions: [
basicSetup,
errorMarkerExtn(),
EditorView.updateListener.of((update) => {
if (
update.docChanged &&
!update.changes.some((change) => change.isUser)
) {
// Ignore changes that are not user-initiated (e.g., programmatic)
return;
}
// update.state.doc holds the current document content

  console.log("Editor content updated:", update.state.doc.toString());
  // Perform your desired actions based on the updated content
}),

],
parent: document.body,
});