class TrumbowygJQry extends InputWidget
{
	// @var array Options for Trumbowyg editor.
	public array $editorOptions = [];
	
	// @var string The HTML tag to be used if not implementing within a form (default: 'textarea').
	public string $tag = 'textarea';
	
	
	// Note: Every protected variable below CacheWidgetTrait is used by the trait
	use CacheWidgetTrait;
	
	protected bool $_debugMode = false;
	protected bool $_compressJsCss = false;
	protected bool $_cacheEnable = false;
	protected int $_cacheJsCssTime = 3600;// +1 hour
	protected string $_cacheKeyPrefix = 'widget_trumbowyg_'; 
	
	const DEFAULT_DURATION_SECONDS = 3600;// +1 hour
	
	public function __construct(array $config = [])
	{
		// Get cacheDuration from Param and set with TimeHelper
		$cacheDuration = ParamHelper::get('widgets.cacheDuration');
		$this->_cacheJsCssTime = TimeHelper::convertDurationToSeconds($cacheDuration);
		
		// Cache & Compression
		$this->_cacheEnable = ParamHelper::get('widgets.cacheEnable');
		$this->_compressJsCss = ParamHelper::get('widgets.compressJsCss');
		
		/**
		* Call to parent constructor
		* The parent constructor should be called last to ensure proper object 
		* initialization and handling of configuration settings.
		*/
		parent::__construct($config);
	}
	
	/**
	* Renders the widget.
	*/
	public function run()
	{
		if ($this->hasModel())
		{
			// Render as a form input for a specific model attribute
			echo Html::activeTextarea($this->model, $this->attribute, $this->options);
		}
		else
		{
			// Render as a standalone HTML element
			echo Html::tag($this->tag, '', $this->options);
		}
		
		// Registers the necessary assets.
		$this->registerAssets();
	}
	
	/**
	* Registers the necessary assets for the Trumbowyg editor.
	*/
	protected function registerAssets(): void
	{
		if (class_exists(TrumbowygAsset::class))
		{
			TrumbowygAsset::register($this->view);
		}
		else
		{
			throw new YiiInvalidConfigException('The Trumbowyg Asset class is not found.');
		}
		
		// Generate the options for the JS initialization
		$options = !empty($this->editorOptions) ? Json::encode($this->editorOptions) : '{}';
		
		// Use either the generated ID for the model attribute or a selector specified in the options
		$id = $this->options['id'] ?? $this->getId();
		
		// Register JavaScript for form submission handling.
		$this->registerJs($id, $options);
	}
	
	/**
	* Registers the JavaScript necessary for form submission via AJAX.
	* @param string $id The unique identifier for the modal.
	*/
	protected function registerJs(string $id, string $options): void
	{
		$cacheKey = $this->_cacheKeyPrefix . $id . '_js_block_';
		$jsBlock = $this->getCachedJsBlock($cacheKey, function () use ($id)
		{
			return <<<JS
				(function(\$)
				{
					/* DOM ready shorthand */
					\$(function()
					{
						\$('#{$id}').trumbowyg({$options});
					});
				})(jQuery);
			JS;
		});
		
		// Register the JavaScript.
		$this->getView()->registerJs($jsBlock, View::POS_END);
	}
}

 PHP Warning – yii\base\ErrorException
Undefined variable $options

        {
            $cacheKey = $this->_cacheKeyPrefix . $id . '_js_block_';
            $jsBlock = $this->getCachedJsBlock($cacheKey, function () use ($id)
            {
                return <<<JS
                    (function(\$)
                    {
                        /* DOM ready shorthand */
                        \$(function()
                        {
                            \$('#{$id}').trumbowyg({$options});
                        });
                    })(jQuery);
                JS;
            });
     
            // Register the JavaScript.
            $this->getView()->registerJs($jsBlock, View::POS_END);
        }
    }