Trix: [Question] How to replace all content but keep undo history?

Created on 7 Jul 2018  路  5Comments  路  Source: basecamp/trix

I tried the following to progamatically update Trix Content:

const trix = document.querySelector('trix-editor');
trix.value = 'new content';

// or
trix.editor.loadHTML('new content');

But both methods don't keep the undo history, digging in the source code both of this methods create a new Document instance and replace the old one, so undo history is lost.

So currently I am doing the following:

````js
const trix = document.querySelector('trix-editor');
const editor = trix.editor;

editor.recordUndoEntry( 'Content updated' );

editor.setSelectedRange( [ 0, trix.value.length ] );
editor.deleteInDirection( 'forward' );
editor.insertHTML( 'new content' );
````

It feels a bit hacky and I noticed there is a method in the models/composition.coffee called replaceHTML that seems to be a better way to do this, but unfortunately it is not exposed through the editor, document or the element.

So: Is there a better way to replace the content progamatically while keeping undo history? If the replaceHTML is the best way to do this, would you consider a PR to expose it through the editor object?

I did not write a PR because the only place where this method is called (controllers/editor_controller.coffee) is right below a comment which says private. So I prefered to ask first.

Thanks.

Most helpful comment

I wonder if there is a better way to avoid trix stelaing focus after inserting new content programmatically

There isn't, currently. "UPDATE 2" looks good. :)

All 5 comments

You can actually get Trix.Composition via

const trix = document.querySelector('trix-editor');
const composition = trix.editor.editorController.composition;

If you go to the constructor of EditorController you can see how the objects fit together and who delegates to what.

Hey @rodrigopedra, what you're doing isn't hacky. I'd make a couple little changes:

  1. Use editor.getDocument().getLength() instead of trix.value.length for the range's end position. value is an HTML string, which will usually be much longer than the document's length.
  2. Skip the editor.deleteInDirection( 'forward' ). editor.insertHTML( 'new content' ) will handle that since it overwrites the selected range.
const { editor } = document.querySelector('trix-editor')

editor.recordUndoEntry('Content updated')
editor.setSelectedRange([0, editor.getDocument().getLength()])
editor.insertHTML('new content')

Thanks @javan it works as expected!

One more question:

After replacing the content the trix-editor steal the focus to itself. How could I avoid that?

Example:

````html




Related issues

marpstar picture marpstar  路  5Comments

madikarizma picture madikarizma  路  5Comments

pars0097 picture pars0097  路  4Comments

divyenduz picture divyenduz  路  3Comments

radcliff picture radcliff  路  5Comments