在Angular2项目中使用Tinymce

时间:2016-07-22 08:11:03

标签: angular tinymce

我正在尝试将 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的头部。 我做错什么了吗?我的初始化不正确吗?

3 个答案:

答案 0 :(得分:5)

这是我在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,这样只有初始化该特定元素而没有其他元素。
  • 我仅在blur个事件发送价值更新,但您可以使用不同的策略,例如使用去抖时间。
  • 我使用DomSanitizer来绕过清理,因为tinymce有时会输出html来触发Angular 2清理。

答案 1 :(得分:3)

我有一个很好的使用Angular2和TinyMCE的工作

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

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

答案 2 :(得分:2)

我是Angular v4决赛。以下是我实施TinyMCE编辑器的方法:

<强>微小-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);
        });
      }
    });
  }
}

创建-article.component.html

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

这个似乎正在运作,虽然在渲染form.value时,内容显示会有一些延迟。