首页 > 解决方案 > 在 downcast 调度程序上更新模型更改视图

问题描述

我需要将 '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”属性。

我希望编辑器中的 html 标记与模型的 id 属性相同。感谢您的帮助,对不起我的英语

标签: ckeditor5

解决方案


C。有几个小问题:

  1. 转换过程可以简化为双向转换器conversion.attributeToAttribute()
  2. 您应该id通过扩展其定义或向模式添加属性检查来允许所有标题上的属性。
  3. 应该通过添加模型的文档 post-fixer来强制执行模型状态。
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' && 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' && 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


推荐阅读