【问题标题】:Using Tinymce in Angular2 project在 Angular2 项目中使用 Tinymce
【发布时间】:2016-07-22 08:11:02
【问题描述】:

我正在尝试将 tinymce 嵌入到我使用 Angular2 构建的网站中。 以下是我的组件:

export class myComponent implements OnInit {
    //some code

    constructor(private af: AngularFire) {
    // some code
    }

    ngOnInit():any {
    tinymce.init(
        {
            selector: ".tinymce",
        });
    }
}

在我的 html 中,有:

<textarea class="tinymce" rows="15"></textarea>

但是有错误说“Cannot find name 'tinymce'”但我已经包含了

<script src='//cdn.tinymce.com/4/tinymce.min.js'></script>

在 html 的头部。 我做错什么了吗?我的初始化不正确吗?

【问题讨论】:

  • 你在使用 webpack 或 systemJS 之类的模块加载器吗?

标签: angular tinymce


【解决方案1】:

这是我自己在 RC6 上使用的。首先我将展示用法:

<h1>The Editor</h1>
<textarea htmlEditor [(ngModel)]="txt"></textarea>
<h1>The HTML Source</h1>
<textarea [(ngModel)]="txt"></textarea>
<h1>The Rendered HTML</h1>
<div [innerHTML]="txt"></div>

所以用法非常简单直接,编辑器的HTML结果移动到textarea的值(我在blur事件上触发更新)

这是指令定义(Typescript):

import {
    Directive,
    OnDestroy,
    AfterViewInit,
    Provider,
    forwardRef,
    HostBinding
} from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { DomSanitizer } from '@angular/platform-browser';

declare var tinymce: any;

export const TinyMceValueAccessor: Provider = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => TinyMceDirective2),
    multi: true
};

// Tinymce directive
@Directive({
    selector: '[htmlEditor]',
    providers: [TinyMceValueAccessor]
})

export class TinyMceDirective2 implements OnDestroy, AfterViewInit, ControlValueAccessor {
    static nextUniqueId = 0;
    @HostBinding('attr.data-tinymce-uniqueid') uniqueId;

    onTouchedCallback: () => void = () => { };
    onChangeCallback: (_: any) => void = () => { };
    innerValue;
    init = false;

    constructor(private sanitizer: DomSanitizer) {
        this.uniqueId = `tinymce-host-${TinyMceDirective2.nextUniqueId++}`;
    }

    //get accessor
    get value(): any {
        return this.innerValue;
    };

    //set accessor including call the onchange callback
    set value(v: any) {
        if (v !== this.innerValue) {
            this.innerValue = v;
            this.onChangeCallback(v);
        }
    }

    ngAfterViewInit(): void {
        console.log('tinymce');
        tinymce.init({
            selector: `[data-tinymce-uniqueid=${this.uniqueId}]`,
            schema: 'html5',
            setup: ed => {
                ed.on('init', ed2 => {
                    if (this.innerValue) ed2.target.setContent(this.innerValue);
                    this.init = true;
                });
            }
        });

        // I chose to send an update on blur, you may choose otherwise
        tinymce.activeEditor.on('blur', () => this.updateValue());
    }

    updateValue() {
        const content = tinymce.activeEditor.getContent();
        this.value = this.sanitizer.bypassSecurityTrustHtml(content);
    }

    writeValue(value): void {
        if (value !== this.innerValue) {
            this.innerValue = value;
            if (this.init && value) tinymce.activeEditor.setContent(value);
        }
    }

    registerOnChange(fn): void {
        this.onChangeCallback = fn;
    }

    registerOnTouched(fn): void {
        this.onTouchedCallback = fn;
    }

    ngOnDestroy(): void {
        if (this.init) tinymce.remove(`[data-tinymce-uniqueid=${this.uniqueId}]`);
    }
}

一些亮点:

  • 我正在使用NG_VALUE_ACCESSOR 提供使用ngModel 的双向绑定
  • 我正在为宿主元素上的自定义属性分配一个唯一的 ID,以便 tinymce 仅初始化该特定元素而不会初始化其他元素。
  • 我仅在 blur 事件上发送值更新,但您可以使用不同的策略,例如使用去抖动时间。
  • 我使用DomSanitizer 绕过清理,因为tinymce 有时会输出触发Angular 2 清理的html。

【讨论】:

  • 一直在尝试这个。我会在页面重新加载时收到一个错误,说 inline template:25:0 由以下原因引起:tinymce 未定义 - 知道为什么吗?
【解决方案2】:

我有一个使用 Angular2 和 TinyMCE 的不错的工作 plunker

<script src="//cdn.tinymce.com/4/tinymce.min.js"></script>

http://plnkr.co/edit/E5Yzk9KT9nSWlPU6i1ZK?p=preview

【讨论】:

    【解决方案3】:

    我在 Angular v4 final 上。下面是我如何实现 TinyMCE 编辑器:

    tiny-editor.component.ts

    imports...
    
    declare var tinymce: any;
    
    const contentAccessor = {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => TinyEditorComponent),
      multi: true
    };
    
    @Component({
      selector: 'app-tiny-editor',
      styleUrls: ['./tiny-editor.component.scss'],
      providers: [contentAccessor],
      template: `
          <textarea id="{{elementId}}"></textarea>
      `
    })
    export class TinyEditorComponent implements AfterViewInit, ControlValueAccessor {
      private onTouch: Function;
      private onModelChange: Function;
    
      registerOnTouched(fn) {
        this.onTouch = fn;
      }
      registerOnChange(fn) {
        this.onModelChange = fn;
      }
    
      writeValue(value) {
        this.editorContent = value;
      }
    
      @Input() elementId: String;
      @Output() onEditorContentChange = new EventEmitter();
    
      constructor() { }
    
      editor;
      editorContent: string = null;
    
      ngAfterViewInit() {
        tinymce.init({
          selector: `#${this.elementId}`,
          plugins: ['link', 'table'],
          skin_url: '../assets/skins/lightgray',
          schema: 'html5',
          setup: editor => {
            this.editor = editor;
            editor.on('keyup change', () => {
              const tinyContent = editor.getContent();
              this.editorContent = tinyContent;
              this.onEditorContentChange.emit(tinyContent);
              this.onModelChange(tinyContent);
              this.onTouch();
              console.log(tinyContent);
            });
          }
        });
      }
    }
    

    create-article.component.html

    <form [formGroup]="form" (ngSubmit)="onSubmit()">
    <app-tiny-editor
       formControlName="content"
       [elementId]="'my-editor'">
    </app-tiny-editor>
    

    似乎可以工作,虽然在渲染 form.value 时内容显示会有些延迟。

    【讨论】:

    • 大约在 5 月,我已经从 PrimeNG 切换到使用 Quill.js 作为其编辑器的编辑器。角度整合似乎要好得多。
    • 感谢您的更新 :) 我打算使用 TinyMCE,但似乎很难再次获得价值。 PrimeNG 很好,我很喜欢,谢谢。
    • 这会抛出一个错误:text-editor.component.ts:59 Uncaught TypeError: _this.onModelChange is not a function on this.onModelChange(content);
    猜你喜欢
    • 1970-01-01
    • 2016-09-05
    • 2016-05-14
    • 1970-01-01
    • 2017-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多