Concepts
Transforms
14min
slate's data structure is immutable, so you can't modify or delete nodes directly instead, slate comes with a collection of "transform" functions that let you change your editor's value slate's transform functions are designed to be very flexible, to make it possible to represent all kinds of changes you might need to make to your editor however, that flexibility can be hard to understand at first π€ check out the transforms docid\ zwt6qv3ijs5h9ftkd9tpl reference for a full list of slate's transforms selection transforms selection related transforms are some of the simpler ones for example, here's how you set the selection to a new range transforms select(editor, { anchor { path \[0, 0], offset 0 }, focus { path \[1, 0], offset 2 }, }) but they can be more complex too for example, it's common to need to move a cursor forwards or backwards by varying distancesβby character, by word, by line here's how you'd move the cursor backwards by three words transforms move(editor, { distance 3, unit 'word', reverse true, }) π€ for more info, check out the transforms docid\ zwt6qv3ijs5h9ftkd9tpl text transforms text transforms act on the text content of the editor for example, here's how you'd insert a string of text as a specific point transforms inserttext(editor, 'some words', { at { path \[0, 0], offset 3 }, }) or you could delete all of the content in an entire range from the editor transforms delete(editor, { at { anchor { path \[0, 0], offset 0 }, focus { path \[1, 0], offset 2 }, }, }) π€ for more info, check out the transforms docid\ zwt6qv3ijs5h9ftkd9tpl node transforms node transforms act on the individual element and text nodes that make up the editor's value for example you could insert a new text node at a specific path transforms insertnodes( editor, { text 'a new string of text ', }, { at \[0, 1], } ) or you could move nodes from one path to another transforms movenodes(editor, { at \[0, 0], to \[0, 1], }) π€ for more info, check out the transforms docid\ zwt6qv3ijs5h9ftkd9tpl the at option many transforms act on a specific location in the document by default, they will use the user's current selection but this can be overridden with the at option for example when inserting text, this would insert the string at the user's current cursor transforms inserttext(editor, 'some words') whereas this would insert it at a specific point transforms inserttext(editor, 'some words', { at { path \[0, 0], offset 3 }, }) the at option is very versatile, and can be used to implement more complex transforms very easily since it is a location it can always be either a path , point , or range and each of those types of locations will result in slightly different transformations for example, in the case of inserting text, if you specify a range location, the range will first be deleted, collapsing to a single point where your text is then inserted so to replace a range of text with a new string you can do transforms inserttext(editor, 'some words', { at { anchor { path \[0, 0], offset 0 }, focus { path \[0, 0], offset 3 }, }, }) or, if you specify a path location, it will expand to a range that covers the entire node at that path then, using the range based behavior it will delete all of the content of the node, and replace it with your text so to replace the text of an entire node with a new string you can do transforms inserttext(editor, 'some words', { at \[0, 0], }) these location based behaviors work for all the transforms that take an at option it can be hard to wrap your head around at first, but it makes the api very powerful and capable of expressing many subtly different transforms the match option many of the node based transforms take a match function option, which restricts the transform to only apply to nodes for which the function returns true when combined with at , match can also be very powerful for example, consider a basic transform that moves a node from one path to another transforms movenodes(editor, { at \[2], to \[5], }) although it looks like it simply takes a path and moves it to another place under the hood two things are happeningβ¦ first, the at option is expanded to be a range representing all of the content inside the node at \[2] which might look something like at { anchor { path \[2, 0], offset 0 }, focus { path \[2, 2], offset 19 } } second, the match option is defaulted to a function that only matches the specific path, in this case \[2] match (node, path) => path equals(path, \[2]) then slate iterates over the range and moves any nodes that pass the matcher function to the new location in this case, since match is defaulted to only match the exact \[2] path, that node is moved but what if you wanted to move the children of the node at \[2] instead? you might consider looping over the node's children and moving them one at a time, but this gets very complex to manage because as you move the nodes the paths you're referring to become outdated instead, you can take advantage of the at and match options to match all of the children transforms movenodes(editor, { // this will again be expanded to a range of the entire node at `\[2]` at \[2], // matches nodes with a longer path, which are the children match (node, path) => path length === 2, to \[5], }) here we're using the same at path (which is expanded to a range), but instead of letting it match just that path by default, we're supplying our own match function which happens to match only the children of the node using match can make representing complex logic a lot simpler for example, consider wanting to add a bold mark to any text nodes that aren't already italic transform setnodes( editor, { bold true }, { // this path references the editor, and is expanded to a range that // will encompass all the content of the editor at \[], // this only matches text nodes that are not already italic match (node, path) => text istext(node) && node italic !== true, } ) when performing transforms, if you're ever looping over nodes and transforming them one at a time, consider seeing if match can solve your use case, and offload the complexity of managing loops to slate instead
π€
Have a question?
Our super-smart AI,knowledgeable support team and an awesome community will get you an answer in a flash.
To ask a question or participate in discussions, you'll need to authenticate first.