One of the features introduced in Elementor 1.8 is Inline Editing. It enables the user to edit the text not only in the Panel but also in the Elementor Preview.

When developing widgets, developers can define which controls will be inline editable. We are going to learn how to do that.

Inline Editing Toolbars

Elementor supports the following types of toolbars for inline editing:

Keep in mind that we recommend to use inline editing the following way:

Adding Inline Editing

Inline editing support is added using the add_inline_editing_attributes() method inside your widget render() and the addInlineEditingAttributes() method in _content_template(). Each inline editing attribute has two parameters:

Adding a new inline editing attributes is done as follows:

protected function render() {
	$this->add_inline_editing_attributes( 'text', 'advanced' );
	echo '<div ' . $this->get_render_attribute_string( 'text_attr' ) . '>' . $this->get_settings( 'text' ) . '</div>';
}

protected function _content_template() {
	?>
	<# view.addInlineEditingAttributes( 'text', 'advanced' ); #>
	<div {{{ view.getRenderAttributeString( 'text' ) }}}>{{{ settings.text }}}</div>
	<?php
}

Example Inline Editing

Full example with three controls all having inline support. A simple text without a toolbar only inline editing, a textarea with a basic toolbar and a wysiwyg with advanced toolbar:

<?php
class Elementor_Test_Widget extends \Elementor\Widget_Base {

	protected function _register_controls() {

		$this->start_controls_section(
			'content_section',
			[
				'label' => __( 'Content', 'plugin-name' ),
				'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
			]
		);

		$this->add_control(
			'title',
			[
				'label' => __( 'Title', 'plugin-name' ),
				'type' => \Elementor\Controls_Manager::TEXT,
				'default' => __( 'Title', 'plugin-name' ),
			]
		);

		$this->add_control(
			'description',
			[
				'label' => __( 'Description', 'plugin-name' ),
				'type' => \Elementor\Controls_Manager::TEXTAREA,
				'default' => __( 'Description', 'plugin-name' ),
			]
		);

		$this->add_control(
			'content',
			[
				'label' => __( 'Content', 'plugin-name' ),
				'type' => \Elementor\Controls_Manager::WYSIWYG,
				'default' => __( 'Content', 'plugin-name' ),
			]
		);

		$this->end_controls_section();

	}

	protected function render() {
		$settings = $this->get_settings_for_display();

		$this->add_inline_editing_attributes( 'title', 'none' );
		$this->add_inline_editing_attributes( 'description', 'basic' );
		$this->add_inline_editing_attributes( 'content', 'advanced' );
		?>
		<h2 <?php echo $this->get_render_attribute_string( 'title' ); ?>><?php echo $settings['title']; ?></h2>
		<div <?php echo $this->get_render_attribute_string( 'description' ); ?>><?php echo $settings['description']; ?></div>
		<div <?php echo $this->get_render_attribute_string( 'content' ); ?>><?php echo $settings['content']; ?></div>
		<?php
	}

	protected function _content_template() {
		?>
		<#
		view.addInlineEditingAttributes( 'title', 'none' );
		view.addInlineEditingAttributes( 'description', 'basic' );
		view.addInlineEditingAttributes( 'content', 'advanced' );
		#>
		<h2 {{{ view.getRenderAttributeString( 'title' ) }}}>{{{ settings.title }}}</h2>
		<div {{{ view.getRenderAttributeString( 'description' ) }}}>{{{ settings.description }}}</div>
		<div {{{ view.getRenderAttributeString( 'content' ) }}}>{{{ settings.content }}}</div>
		<?php
	}

}