2016-07-22 15 views
3

Ich versuche, tinymce in meine Website, die mit Angular2 gebaut wird einzubetten. Folgende ist meine Komponente:Mit Tinymce in Angular2 Projekt

export class myComponent implements OnInit { 
    //some code 

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

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

Und mein html in Seite gibt es:

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

Aber es gibt Fehler "Cannot find name 'tinymce'" aber ich habe zu sagen sind bereits

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

innen der Kopf von HTML. Habe ich etwas falsch gemacht? Ist meine Initialisierung falsch?

+0

verwenden Sie einen Modullader wie Webpack oder SystemJS? – shusson

Antwort

5

Hier ist, was ich für mich selbst verwendet habe, auf RC6. Zunächst werde ich die Verwendung zeigen:

<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> 

So ist die Nutzung ist ziemlich einfach und unkompliziert, das HTML-Ergebnis des Editors auf den Wert des textarea bewegt (ich das Update auf blur Ereignis auslösen)

Und hier ist die Richtlinie Definition (Typoskript):

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}]`); 
    } 
} 

Einige Highlights:

  • Ich verwende NG_VALUE_ACCESSOR, um eine Zwei-Wege-Bindung unter Verwendung von ngModel
  • zu schaffen. Ich weise einem benutzerdefinierten Attribut auf dem Host-Element eine eindeutige ID zu, so dass tinymce nur dieses spezifische Element und keine anderen initialisiert.
  • Ich sende Wert Updates nur auf blur Ereignisse, aber Sie können eine andere Strategie verwenden, zum Beispiel mit Debounce-Zeit.
  • Ich benutze DomSanitizer um Hygienisierung zu umgehen, da tinymce manchmal HTML ausgibt, die Angular 2 Sanitisierung auslöst.
+0

Ich habe dieses eine versucht.Ich erhalte einen Fehler beim Umladen der Seite mit der Inline-Vorlage: 25: 0 verursacht durch: tinymce ist nicht definiert - irgendeine Idee, warum? – catu

2

auf Angular v4 final Ich bin mit verwenden. Hier ist, wie ich den TinyMCE Editor implementiert:

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> 

Diese scheint zu sein, funktioniert, obwohl beim Rendern des form.value eine gewisse Verzögerung beim Anzeigen des Inhalts auftritt.

+1

Ab etwa Mai wechselte ich von PrimeNG zum Editor, der Quill.js als Editor verwendet. Die Winkelintegration scheint viel besser zu sein. – markgoho

+0

Danke für das Update :) Ich wollte TinyMCE verwenden, aber es schien mir eine große Mühe, den Wert wieder herauszuholen. Guten Ruf auf PrimeNG Ich mag es, danke. –

+0

Dies wirft einen Fehler: '' 'text-editor.component.ts: 59 Uncaught TypeError: _this.onModelChange ist keine Funktion' '' auf '' 'this.onModelChange (content);' '' –