Monday 12 June 2017

Forwarding keyUp and change events from TinyMCE editor to TextArea element using Angular 4 Reactive Forms

I have an ReactiveForm in angular 4 in which I want to use TinyMCE to allow the users to format the text that would go inside and textarea.

I have created an component to host my TinyMCE editor, just like below (tinymce.component.ts):

import { Component, AfterViewInit, ViewChild, EventEmitter, forwardRef, ElementRef, OnDestroy, Input, Output } from '@angular/core';
import { 
ControlValueAccessor, 
NG_VALUE_ACCESSOR, 
NG_VALIDATORS, 
FormControl, 
Validator 
} from '@angular/forms';

@Component({
selector: 'tinymce',
templateUrl: './tinymce.component.html',
providers: [
{
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => TinyMCEComponent),
  multi: true,
},
{
  provide: NG_VALIDATORS,
  useExisting: forwardRef(() => TinyMCEComponent),
  multi: true,
}]
})
export class TinyMCEComponent implements ControlValueAccessor, Validator, AfterViewInit, OnDestroy {
@Input() elementId: String;

constructor(private el: ElementRef) { }

editor;

content: string = 'weee';
private parseError: boolean;

// the method set in registerOnChange, it is just 
// a placeholder for a method that takes one parameter, 
// we use it to emit changes back to the form
private propagateChange = (_: any) => { };

// this is the initial value set to the component
public writeValue(obj: any) {
    if (obj) {
        this.content =  obj; 
    }
}

// registers 'fn' that will be fired when changes are made
// this is how we emit the changes back to the form
public registerOnChange(fn: any) {
    this.propagateChange = fn;
}

// not used, used for touch input
public registerOnTouched() { }

// change events from the textarea
private onChange(event) {
    $("#" + this.elementId).change();
    // update the form
    this.propagateChange(this.content);
}

// returns null when valid else the validation object 
// in this case we're checking if the json parsing has 
// passed or failed from the onChange method
public validate(c: FormControl) {
    return (!this.parseError) ? null : {
        jsonParseError: {
            valid: false,
        },
    };
}

ngAfterViewInit() {
    tinymce.init({
        selector: '#' + this.elementId,
        plugins: ['link', 'paste', 'table'],
        skin_url: '../assets/skins/lightgray',
        setup: editor => {
            this.editor = editor;
            editor.on('keyup', () => {
                this.content = editor.getContent();
                this.onChange(null);
            });
        }
    });
}

ngOnDestroy() {
    tinymce.remove(this.editor);
}
}

Then I have the component html (tinymce.component.html):

<textarea
#conteudo
id=""
[value]="content"
(change)="onChange($event)" 
(keyup)="onChange($event)">
</textarea>

And my form:

    <form [formGroup]="procedimentoForm" class="ui form">
      <div class="field">
    <label>Conteúdo</label>
    <tinymce formControlName="conteudo" [elementId]="'conteudo'"></tinymce>
  </div>

</form>

I would like that for any change in the TinyMCE editor (at keyup, for example), the formcontrol would get its value updated. The way it's working at the moment, only after I change the focus to another formcontrol the "parametroForm.value.conteudo" get updated in the form.



via Alaor

No comments:

Post a Comment