Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
384 views
in Technique[技术] by (71.8m points)

ckeditor5 - How to programatically insert link at current position in CKEditor 5

In my app, I have a specific dialog to create internal links. After user finishes filling the dialog I want to programatically insert generated link to current caret position in the editor. So far I've been using SummerNote and there it is easy:

editor.summernote('createLink', {
     text: linkTitle,
     url: url
});

In CKEditor 5 I found this method which seems like it could do what I need:

doc.enqueueChanges(() => {
    editor.data.insertContent(content, doc.selection);
});

My problem is that I don't know how to create this "content" parameter. I tried to create a link in HTML and pass it there, but that doesn't work.

I also tried to create an instance of LinkElement, but that class doesn't seem to exist in the JS runtime (I'm running CKEditor from build, not from sources).

It's not clear to me if this is even possible without writing a plugin for CKEditor (which seems to me like an overkill).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

After 1.0.0-beta (March 2018):

To insert some data into an editor, simply use a "change block":

editor.model.change( writer => {
    const insertPosition = editor.model.document.selection.getFirstPosition();
    writer.insertText( linkText, { linkHref: linkUrl }, insertPosition );
} );

where linkText and linkUrl are variables that you should provide from your custom UI.

The above will work well for collapsed selection. The linked text will be inserted at caret position.

The big difference introduced in 1.0.0-beta is that we are providing the writer object in change() calls, so you don't need to (and should not) use framework classes constructors directly.

You can also use editor.model.insertContent in a similar way that you proposed:

editor.model.change( writer => {
    const linkedText = writer.createText( linkText, { linkHref: linkUrl } );
    editor.model.insertContent( linkedText, editor.model.document.selection );
} );

This will work properly also if the selection is not collapsed, as insertContent does a little bit more (for example, if selection was not collapsed and was between two paragraphs, selection contents will be removed and paragraphs merged).

Before 1.0.0-beta

DataController#insertContent() accepts model's DocumentFragment or Node (so Element or TextI've just noticed that this info is missing in the API docs).

Unfortunately, right now you need to have access to Element's or Text's constructors in order to create them. This means that you need to build CKEditor 5 from source instead of using existing builds. This isn't hard, but it's indeed an overkill. Therefore, we're working now on exposing a sufficient part of the API in the existing classes so that you could write simple integration code like this without building CKEditor 5 into your app.

Anyway, if you'll configure webpack (or simply fork an existing build) you can write a simple function for inserting a linked text:

import Text from '@ckeditor/ckeditor5-engine/src/model/text';

function insertLink( linkText, linkHref ) {
    const text = new Text( linkText, { linkHref } );

    editor.document.enqueueChanges( () => {
        editor.data.insertContent( text, editor.document.selection );
    } );
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...