Using Tinymce in Angular2 project

前端 未结 3 1831
一整个雨季
一整个雨季 2020-12-06 15:09

I\'m trying to embed tinymce into my website which is built using Angular2. Following is my component:

export class myComponent implements          


        
3条回答
  •  独厮守ぢ
    2020-12-06 15:36

    Here's what I've used for myself, on RC6. First I'll show the usage:

    The Editor

    The HTML Source

    The Rendered HTML

    So the usage is pretty simple and straightforward, the HTML result of the editor is moved to the value of the textarea (I trigger the update on blur event)

    And here's the directive definition (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}]`);
        }
    }
    

    Some highlights:

    • I'm using NG_VALUE_ACCESSOR to provide for two way binding using ngModel
    • I'm assigning a unique id to a custom attribute on the host element so that tinymce only initializes that specific element and no others.
    • I'm sending value updates only on blur events, but you may use a different strategy, for example using debounce time.
    • I'm using DomSanitizer to bypass sanitization, since tinymce sometimes outputs html which triggers Angular 2 sanitization.

提交回复
热议问题