Add WYSIWYG (TinyMCE) field type to Elementor forms

Despite all the power and rich options available with the standard Elementor Pro form fields, sometimes a TinyMCE WYSIWYG editor field is exactly the right tool for the job. Here’s how you can add that as a field type so users can input rich text into an Elementor form. Although there is a lot of code involved, it’s all copy-n-paste…you don’t have to understand the whole thing. That said, you should be comfortable making edits to either a custom plugin or theme functions.php file. Here goes!

A little history…in November 2018 I needed a WYSIWYG field for a social media feature I was adding to a site. I was too much of a tightwad to buy an add-on, so I asked the folks at the Elementor Github site to add this as a feature request in issue #6139. They declined, but at least provided the code I could use to do it myself.

It all starts with this big blob of code. Put it into a file that you can include from either a plugin or theme. To save you the trouble of an awkward copy-n-paste, you can download mine: class_Elementor_Form_Field_Type_Wysiwyg.php. Note that for security reasons, I had to change the .php filename extension to .txt.

<?php

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

class Wysiwyg extends ElementorPro\Modules\Forms\Fields\Field_Base {

	public $depended_scripts = [
		'tinymce-cdn',
	];

	public function get_type() {
		return 'wysiwyg';
	}

	public function get_name() {
		return __( 'Wysiwyg', 'elementor-pro' );
	}

	/**
	 * @param      $item
	 * @param      $item_index
	 * @param Form $form
	 */
	public function render( $item, $item_index, $form ) {

		$form->add_render_attribute( 'textarea' . $item_index, 'class', 'elementor-tinymce' );

		echo '<textarea ' . $form->get_render_attribute_string( 'input' . $item_index ) . '></textarea>';
	}

	public function register_field_type( $fields ) {
		ElementorPro\Plugin::instance()->modules_manager->get_modules( 'forms' )->add_form_field_type( self::get_type(), $this );
		$fields[ self::get_type() ] = self::get_name();
		return $fields;
	}

	public function front_end_inline_JS() {
		?>
		<script>
			var ElementorFormWysiwyg = ElementorFormWysiwyg || {};
			jQuery( document ).ready( function( $ ) {
				ElementorFormWysiwyg = {
					onReady: function( callback ) {
						if ( window.tinymce ) {
							callback();
						} else {
							// If not ready check again by timeout..
							setTimeout( function() {
								ElementorFormWysiwyg.onReady( callback );
							}, 350 );
						}
					},
					init: function() {
						self = this;
						this.onReady( function() {
							tinymce.init({
								selector: 'textarea[type="wysiwyg"]',
								setup: function (editor) {
									editor.on('change', function () {
										editor.save();
									});
								},
								menubar: true,
								// plugins: 'preview searchreplace autolink directionality visualblocks visualchars image link media template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists textcolor wordcount imagetools contextmenu colorpicker textpattern help',
                                plugins: 'autolink charmap colorpicker contextmenu help hr image imagetools link lists media nonbreaking searchreplace table textcolor wordcount',
								toolbar: 'formatselect | bold italic strikethrough forecolor backcolor | link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat | image table media'
							});
						} );
					}
				};
				ElementorFormWysiwyg.init();
			} );
		</script>
		<?php
	}

	public function editor_inline_JS() {
		add_action( 'wp_footer', function() {
		?>
		<script>
			var ElementorFormWysiwygField = ElementorFormWysiwygField || {};
			jQuery( document ).ready( function( $ ) {
				ElementorFormWysiwygField = {
					onReady: function( callback ) {
						if ( window.tinymce ) {
							callback();
						} else {
							// If not ready check again by timeout..
							setTimeout( function() {
								ElementorFormWysiwygField.onReady( callback );
							}, 350 );
						}
					},
					renderField: function( inputField, item, i, settings ) {
						var itemClasses = item.css_classes,
							required = '',
							fieldName = 'form_field_';

						if ( item.required ) {
							required = 'required';
						}
						return '<textarea type="wysiwyg" class="elementor-wysiwyg elementor-field ' + itemClasses + '" name="' + fieldName + '" id="form_field_' + i + '" ' + required + '></textarea>';
					},
					initTinyMce: function() {
						tinymce.remove();
						tinymce.init({
							selector: 'textarea[type="wysiwyg"]',
							setup: function (editor) {
								editor.on('change', function () {
									editor.save();
								});
							},
							menubar: false,
							plugins: 'preview searchreplace autolink directionality visualblocks visualchars image link media template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists textcolor wordcount imagetools contextmenu colorpicker textpattern help',
							toolbar: 'formatselect | bold italic strikethrough forecolor backcolor | link | alignleft aligncenter alignright alignjustify  | numlist bullist outdent indent  | removeformat | image table media'
						});
					},
					init: function() {
						self = this;
						this.onReady( function() {
							elementorFrontend.hooks.addAction( 'frontend/element_ready/form.default', ElementorFormWysiwygField.initTinyMce );
							elementor.hooks.addFilter( 'elementor_pro/forms/content_template/field/wysiwyg', ElementorFormWysiwygField.renderField, 10, 4 );
						} );
					}
				};
				ElementorFormWysiwygField.init();
			} );
		</script>
		<?php
		} );
	}

	public function sanitize_field( $value, $field ) {
		return wp_kses_post( $field['raw_value'] );
	}

	public function __construct() {
		parent::__construct();
		add_filter( 'elementor_pro/forms/field_types', [ $this, 'register_field_type' ] );
		add_action( 'wp_footer', [ $this, 'front_end_inline_JS' ] );
		add_action( 'elementor/preview/init', [ $this, 'editor_inline_JS' ] );
		wp_register_script( 'tinymce-cdn', 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.8.5/tinymce.min.js' );
	}
}

?>

Once that file is tucked away, you need to pull it from your plugin or theme like this:

add_action( 'elementor_pro/init', function() {
    require_once( __DIR__ . '/inc/class_Elementor_Form_Field_Type_Wysiwyg.php' );
    new Wysiwyg();
} );

Now, when you edit a form, you should see the Wysiwyg field type at the bottom of the field type dropdown, like so:

Add WYSIWYG (TinyMCE) field type to Elementor forms | Elementor forms, php, wysiwyg-field-type

Hope you enjoy this new feature. If there’s enough demand, maybe I’ll set it up as a standalone plugin.

Leave a Reply

Your email address will not be published. Required fields are marked *