I think I have a misunderstanding of how transactions and selection work.
I have a transaction where I insert a large amount of content at the end of a document and I want to have the selection move into that new content at a given offset. I can’t make it work in a single transaction without getting RangeErrors on the tr.setSelection call. The only way I can get it to work is in a setTimeout call after dispatching the insert transaction. What am I missing this can’t be normal.
You should definitely be able to set a new selection in the same transaction that inserts content. Dispatching multiple transactions for that isn’t necessary (and is generally a bad idea). Can you show the code that creates this transaction?
Here is a block of code that demonstrates what I am trying to do and does not work. I added a comment to explain the range error as that part was my misunderstanding
import { DOMParser as ProseMirrorDOMParser } from "prosemirror-model";
...
let sequence = "<p>Test line just for content to test with</p>"
let html = sequence.repeat(200)
const domParser = new DOMParser();
const parsedHTML = domParser.parseFromString(html, "text/html").body;
// Convert DOM to ProseMirror-compatible document fragment
const docNode = ProseMirrorDOMParser.fromSchema(editor.schema).parse(parsedHTML);
// Put the cursor at the end of first Child or 2 if for some reason this fails
const pos = docNode.firstChild?.nodeSize ?? 2
tr = tr.insert(0, docNode)
// This version never does anything
//tr = tr.setSelection(TextSelection.create(tr.doc, 0, pos - 1 ))
// Nor does this but its essentially the same
const resolvedPos = tr.doc.resolve(pos - 1);
tr = tr.setSelection(TextSelection.create(tr.doc, 0, resolvedPos.pos))
// This one throws the Range Error which I understand is correct because I misunderstood that pos has to be
// a position before the insert
//const mappedPos = tr.mapping.map(pos);
//tr = tr.setSelection(TextSelection.create(tr.doc, 0, mappedPos))
dispatch(tr);
There’s no guarantee that the content in docNode can be inserted in the document as-is. (In fact, it’s unlikely that your document node type allows itself as a child, so it’ll definitely get mangled by the replace logic, in the process of being inserted.) As such, blindly using the side of its first (?) child as a document position isn’t safe. You could try tr.mapping.map(0, 1) to find the position after the insertion.
And you’ll want to use TextSelection.between with the resolved position, not create, when you aren’t certain that the position is a valid inline position.
Changing to this does not work either. No logged error and resolved positions are 0 and 40 so something should have been selected within that region as the content in the transaction does appear in the doc
Look, new DOMParser(), without arguments, isn’t a thing in ProseMirror’s interface, and neither does DOMParser have a parseFromString method, so I wasn’t able to do anything with that code.
I see. Including the import statements would have helped there. I don’t really understand what you’re trying to do, but setSelection with the result of TextSelection.between seems to work fine for me.