Обновить представление об изменении модели в downcast dispatcher

#ckeditor5

#ckeditor5

Вопрос:

Мне нужно добавить ‘id’ attr к элементам заголовка, у которых его нет.

Я пытаюсь это сделать

 conversion.for('upcast').elementToElement({
   model: (viewElement, modelWriter) => {
      const attrs = {};
      const id = viewElement.getAttribute('id');


      if (id) {
         attrs['id'] = id;
      }

      return modelWriter.createElement('heading1', attrs);
   },
   view: {
      name: 'h1'
   },
   converterPriority: 'low'   1
});

conversion.for('downcast').add(dispatcher => {
   dispatcher.on('insert:heading1', (evt, data, conversionApi) => {
      if (!data.item.getAttribute('id')) {
         conversionApi.writer.setAttribute('id', generateUID(), data.item)
      }
   });
});

conversion.for('downcast').attributeToAttribute({
   model: {
      name: 'heading1',
      key: 'id'
   },
   view: {
      name: 'h1',
      key: 'id'
   }
});

editor.conversion.elementToElement(option);

modelElements.push(option.model);
  

и это изменило модель с

 <$root>
   <heading1 id="ykuqo5" >some text</heading1>
</$root>
  

но у представления все еще нет ‘id’ attr.

Я ожидаю, что HTML-тег в редакторе будет иметь идентификатор, соответствующий модели. Спасибо за помощь, извините за мой английский

Ответ №1:

c. Есть несколько незначительных проблем:

  1. Процесс преобразования может быть упрощен до двустороннего конвертера conversion.attributeToAttribute() .
  2. Вы должны разрешить id атрибут для всех заголовков либо расширив их определения, либо добавив проверку атрибута в схему.
  3. Принудительное изменение состояния модели должно быть выполнено путем добавления исправления документа модели.
 class HeadingIdAttribute extends Plugin {
    init() {
        const editor = this.editor;
        const model = editor.model;
        const conversion = editor.conversion;

        // Allow 'id' attribute on heading* elements:

        // Either by extending each heading definition:
        // editor.model.schema.extend( 'heading1', { allowAttributes: [ 'id' ] } );
        // editor.model.schema.extend( 'heading2', { allowAttributes: [ 'id' ] } );
        // editor.model.schema.extend( 'heading3', { allowAttributes: [ 'id' ] } );

        // or by adding a more general attribute check:
        model.schema.addAttributeCheck( ( schemaContext, attribute ) => {
            if ( attribute == 'id' amp;amp; isHeading( schemaContext.last.name ) ) {
                return true;
            }
        } );

        // Then the conversion might be a two way attribute-to-attribute:
        conversion.attributeToAttribute( {
            model: 'id',
            view: 'id'
        } );

        // Register a model post-fixer to add missing id attribute 
        // to the heading* element.
        model.document.registerPostFixer( writer => {
            let wasChanged = false;

            // Get changes
            const changes = model.document.differ.getChanges();

            for ( const change of changes ) {
                // Check heading nodes on insert.
                if ( change.type == 'insert' amp;amp; isHeading( change.name ) ) {
                    const heading = change.position.nodeAfter;

                    // Set 'id' attribute when it is missing in the model.
                    if ( !heading.hasAttribute( 'id' ) ) {
                        writer.setAttribute( 'id', uid(), heading );

                        // Return true to notify that model was altered.
                        wasChanged = true;
                    }
                }
            }

            return wasChanged;
        } );

        // Helper method for checking if name is any heading element.
        // Detects default headings: 'heading1', 'heading2', ... 'heading6'.
        function isHeading( name ) {
            return name.slice( 0, -1 ) == 'heading';
        }
    }
}
  

И добавьте этот плагин в свой редактор (не забудьте добавить также другие плагины):

 ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ Enter, Typing, Undo, Heading, Paragraph, HeadingIdAttribute ],
        toolbar: [ 'heading', '|', 'undo', 'redo' ]
    } )
    .then( editor => {
        window.editor = editor;
    } )
    .catch( err => {
        console.error( err.stack );
    } );
  

Это также создаст атрибут id для представления:

Абзац изменен на заголовок 3