Here's some example HTML I'm trying to produce:
<div>
<input type="checkbox" id="checkbox_1" name="checkbox_1" />
<label for="checkbox_1"></label>
</div>
This is my downcast converter:
conversion.for( 'downcast' ).elementToElement( {
model: 'checkbox',
view: ( modelElement, viewWriter ) => {
const div = viewWriter.createContainerElement( 'div', {} );
const input = viewWriter.createEmptyElement( 'input', {'type': 'checkbox'} );
const label = viewWriter.createEditableElement( 'label', {} );
viewWriter.insert( viewWriter.createPositionAt( div, 0 ), input );
viewWriter.insert( viewWriter.createPositionAt( div, 1 ), label );
return toWidgetEditable( div, viewWriter );
}
} );
In the CKEditor 5 inspector, I can see that the view is rendered like this:
<div contenteditable="true" class="ck-editor__editable ck-editor__nested-editable">
<input type="checkbox" />
<label>
</label>
</div>
In the editor, I can't add text to the label or the surrounding div.
If I change the div
declaration from createContainerElement
to createEditableElement
, I can insert text in the div, but I still can't edit the label.
How do I set up the converters so that I can have an editable label attached to my <input>
? I've tried looking at the todolist
code from ckeditor5-list
, but it doesn't use conversion.for
or elementToElement
at all, so I'm a bit lost.
The code that you posted is incorrect because you cannot create view elements like that, out of the blue. They need to be mapped to something in the model if they are supposed to be editable. Unless this was supposed to be a non-editable region. In which case you should use toWidget()
not to toWidgetEditable()
.
The second problem is that using focusable fields inside the editor has to be done very carefully. Such elements must be inside a non-editable part of the widget, plus, you need to stop the editor from handling events on them. This, currently, can only be achieved with a hack:
// Hack needed to make the input fields accessible and responsive when used in a widget.
function preventCKEditorHandling( domElement, editor ) {
// Prevent the editor from listening on below events in order to stop rendering selection.
domElement.addEventListener( 'click', stopEventPropagationAndHackRendererFocus, { capture: true } );
domElement.addEventListener( 'mousedown', stopEventPropagationAndHackRendererFocus, { capture: true } );
domElement.addEventListener( 'focus', stopEventPropagationAndHackRendererFocus, { capture: true } );
// Prevents TAB handling or other editor keys listeners which might be executed on editors selection.
domElement.addEventListener( 'keydown', stopEventPropagationAndHackRendererFocus, { capture: true } );
function stopEventPropagationAndHackRendererFocus( evt ) {
evt.stopPropagation();
// This prevents rendering changed view selection thus preventing to changing DOM selection while inside a widget.
editor.editing.view._renderer.isFocused = false;
}