\
@@ -156,6 +161,9 @@
if (this.itemType == 'property' && this.groupIndex !== undefined)
result += self.groupExpanded(this.group) ? ' expanded' : ' collapsed'
+ if (this.itemType == 'property' && this.noExternalParameter)
+ result += ' no-external-parameter'
+
return result
}
},
@@ -211,7 +219,7 @@
width: 400
})
- self.$el.on('hiding.oc.popover', function(e){self.onBeforeHide(e)})
+ self.$el.on('hiding.oc.popover', function(e){return self.onBeforeHide(e)})
self.$el.on('hide.oc.popover', function(){self.cleanup()})
self.$el.addClass('inspector-open')
@@ -225,12 +233,15 @@
self.editors[0].focus()
}
+ if (self.$el.closest('[data-inspector-external-parameters]').length > 0)
+ self.initExternalParameterEditor(self.$el.data('oc.popover').$container)
+
$.each(self.editors, function(){
if (this.init !== undefined)
this.init()
})
- $('[data-toggle=tooltip]', self.$el.data('oc.popover').$container).tooltip({placement: 'auto right', container: 'body'})
+ $('[data-toggle=tooltip]', self.$el.data('oc.popover').$container).tooltip({placement: 'auto right', container: 'body', delay: 500})
var $container = self.$el.data('oc.popover').$container
$container.on('click', 'tr.group', function(){
@@ -248,6 +259,145 @@
displayPopover()
}
+ /*
+ * Initializes the external parameter editors for properties that support this feature.
+ */
+ Inspector.prototype.initExternalParameterEditor = function($container) {
+ var self = this
+
+ $('table.inspector-fields tr', $container).each(function(){
+ if (!$(this).hasClass('no-external-parameter')) {
+ var property = $(this).data('property'),
+ $td = $('td', this),
+ $editorContainer = $(''),
+ $editor = $(
+ '')
+
+ $editorContainer.append($td.children())
+ $editorContainer.append($editor)
+ $td.append($editorContainer)
+
+ var $editorLink = $('a', $editor)
+
+ $editorLink.click(function() {
+ return self.toggleExternalParameterEditor($(this))
+ })
+ .attr('title', 'Click to enter the external parameter name to load the property value from')
+ .tooltip({'container': 'body', delay: 500})
+
+ var $input = $editor.find('input'),
+ propertyValue = self.propertyValues[property]
+
+ $input.on('focus', function(){
+ var $field = $(this)
+
+ $('td', $field.closest('table')).removeClass('active')
+ $field.closest('td').addClass('active')
+ })
+
+ $input.on('change', function(){
+ self.markPropertyChanged(property, true)
+ })
+
+ var matches = []
+ if (matches = propertyValue.match(/^\{\{([^\}]+)\}\}$/)) {
+ var value = $.trim(matches[1])
+
+ if (value.length > 0) {
+ self.showExternalParameterEditor($editorContainer, $editor, $editorLink, $td, true)
+ $editor.find('input').val(value)
+ self.writeProperty(property, null, true)
+ }
+ }
+ }
+ })
+ }
+
+ Inspector.prototype.showExternalParameterEditor = function($container, $editor, $editorLink, $cell, noAnimation) {
+ var position = $editor.position()
+ $('input', $editor).focus()
+
+ if (!noAnimation) {
+ $editor.css({
+ 'left': position.left + 'px',
+ 'right': 0
+ })
+ } else
+ $editor.css('right', 0)
+
+ setTimeout(function(){
+ $editor.css('left', 0)
+ $cell.scrollTop(0)
+ }, 0)
+
+ $container.addClass('editor-visible')
+ $editorLink.attr('data-original-title', 'Click to enter the property value')
+ this.toggleCellEditorVisibility($cell, false)
+ $editor.find('input').attr('tabindex', 0)
+ }
+
+ Inspector.prototype.toggleExternalParameterEditor = function($editorLink) {
+ var $container = $editorLink.closest('.external-param-editor-container'),
+ $editor = $('.external-editor', $container),
+ $cell = $editorLink.closest('td'),
+ self = this
+
+ $editorLink.tooltip('hide')
+
+ if (!$container.hasClass('editor-visible')) {
+ self.showExternalParameterEditor($container, $editor, $editorLink, $cell)
+ } else {
+ var left = $container.width()
+
+ $editor.css('left', left + 'px')
+ setTimeout(function(){
+ $editor.css({
+ 'left': 'auto',
+ 'right': '30px'
+ })
+ $container.removeClass('editor-visible')
+ $container.closest('td').removeClass('active')
+ }, 200)
+ $editorLink.attr('data-original-title', 'Click to enter the external parameter name to load the property value from')
+ $editor.find('input').attr('tabindex', -1)
+ self.toggleCellEditorVisibility($cell, true)
+ }
+
+ return false
+ }
+
+ Inspector.prototype.toggleCellEditorVisibility = function($cell, show) {
+ var $container = $('.external-param-editor-container', $cell)
+
+ $container.children().each(function(){
+ var $el = $(this)
+
+ if ($el.hasClass('external-editor'))
+ return
+
+ if (show)
+ $el.removeClass('hide')
+ else {
+ var height = $cell.data('inspector-cell-height')
+
+ if (!height) {
+ height = $cell.height()
+ $cell.data('inspector-cell-height', height)
+ }
+
+ $container.css('height', height + 'px')
+ $el.addClass('hide')
+ }
+ })
+ }
+
/*
* Creates group nodes in the property set
*/
@@ -379,17 +529,22 @@
return null
}
- Inspector.prototype.writeProperty = function(property, value) {
+ Inspector.prototype.writeProperty = function(property, value, noChangedStatusUpdate) {
this.propertyValues[property] = value
this.propertyValuesField.val(JSON.stringify(this.propertyValues))
if (this.originalPropertyValues[property] === undefined || this.originalPropertyValues[property] != value) {
- this.$el.trigger('change')
- this.markPropertyChanged(property, true)
- } else
- this.markPropertyChanged(property, false)
+ if (!noChangedStatusUpdate) {
+ this.$el.trigger('change')
+ this.markPropertyChanged(property, true)
+ }
+ } else {
+ if (!noChangedStatusUpdate)
+ this.markPropertyChanged(property, false)
+ }
- this.$el.trigger('propertyChanged.oc.Inspector', [property])
+ if (!noChangedStatusUpdate)
+ this.$el.trigger('propertyChanged.oc.Inspector', [property])
return value
}
@@ -412,6 +567,7 @@
var editor = new $.oc.inspector.editors[editorClass](editorId, this, data)
this.editors.push(editor)
+ editor.inspectorCellId = editorId
return editor.renderEditor()
}
@@ -429,11 +585,40 @@
}
Inspector.prototype.onBeforeHide = function(e) {
+ var $container = this.$el.data('inspector-container'),
+ externalParamErrorFound = false,
+ self = this
+
$.each(this.editors, function() {
- this.applyValue()
+ if (!self.editorExternalPropertyEnabled(this))
+ this.applyValue()
+ else {
+ var $cell = $('#'+this.inspectorCellId, $container),
+ $extPropEditorContainer = $cell.find('.external-param-editor-container'),
+ $input = $extPropEditorContainer.find('.external-editor input'),
+ val = $.trim($input.val())
+
+ if (val.length == 0) {
+ alert('Please enter external parameter name for the '+this.fieldDef.title+' property.')
+ externalParamErrorFound = true
+ setTimeout(function(){
+ $input.focus()
+ }, 0)
+ return false
+ }
+
+ self.writeProperty(this.fieldDef.property, '{{ '+val+' }}')
+ }
})
- var eH = $.Event('hiding.oc.inspector')
+ if (externalParamErrorFound) {
+ e.preventDefault()
+ return false
+ }
+
+ var eH = $.Event('hiding.oc.inspector'),
+ ispector = this
+
this.$el.trigger(eH, [{values: this.propertyValues}])
if (eH.isDefaultPrevented()) {
e.preventDefault()
@@ -441,6 +626,9 @@
}
$.each(this.editors, function() {
+ if (ispector.editorExternalPropertyEnabled(this))
+ return true
+
if (this.validate === undefined)
return true
@@ -458,10 +646,17 @@
return false
})
- var $contianer = this.$el.data('inspector-container')
$('[data-toggle=tooltip]', this.$el.data('oc.popover').$container).tooltip('hide')
}
+ Inspector.prototype.editorExternalPropertyEnabled = function(editor) {
+ var $container = this.$el.data('inspector-container'),
+ $cell = $('#'+editor.inspectorCellId, $container),
+ $extPropEditorContainer = $cell.find('.external-param-editor-container')
+
+ return $extPropEditorContainer.hasClass('editor-visible')
+ }
+
//
// EDITOR DEFINITIONS
// ==================
@@ -474,6 +669,7 @@
* - validate(), optional, validates the value and returns the validation error message
* - applyValue(), applies the editor value
* - focus(), focuses the editor input element, if applicable
+ * - init(), sets the initial editor value
*/
// STRING EDITOR
@@ -483,7 +679,7 @@
this.inspector = inspector
this.fieldDef = fieldDef
this.editorId = editorId
- this.selector = '#'+this.editorId+' input'
+ this.selector = '#'+this.editorId+' input.string-editor'
var self = this
$(document).on('focus', this.selector, function() {
@@ -498,6 +694,11 @@
})
}
+ InspectorEditorString.prototype.init = function() {
+ var value = $.trim(this.inspector.readProperty(this.fieldDef.property))
+ $(this.selector).val(value)
+ }
+
InspectorEditorString.prototype.applyValue = function() {
this.inspector.writeProperty(this.fieldDef.property, $.trim($(this.selector).val()))
}
@@ -505,11 +706,10 @@
InspectorEditorString.prototype.renderEditor = function() {
var data = {
id: this.editorId,
- value: $.trim(this.inspector.readProperty(this.fieldDef.property)),
placeholder: this.fieldDef.placeholder !== undefined ? this.fieldDef.placeholder : ''
}
- return Mustache.render(' | ', data)
+ return Mustache.render('
| ', data)
}
InspectorEditorString.prototype.validate = function() {
@@ -525,6 +725,7 @@
InspectorEditorString.prototype.focus = function() {
$(this.selector).focus()
+ $(this.selector).closest('td').scrollLeft(0)
}
$.oc.inspector.editors.inspectorEditorString = InspectorEditorString;
@@ -550,14 +751,8 @@
}
InspectorEditorCheckbox.prototype.renderEditor = function() {
- var isChecked = this.inspector.readProperty(this.fieldDef.property)
-
- if (isChecked == '0' || isChecked == 'false')
- isChecked = false
-
var data = {
id: this.editorId,
- checked: isChecked ? 'checked' : null,
cbId: this.editorId + '-cb',
title: this.fieldDef.title
}
@@ -565,6 +760,15 @@
return Mustache.render(this.getTemplate(), data)
}
+ InspectorEditorCheckbox.prototype.init = function() {
+ var isChecked = this.inspector.readProperty(this.fieldDef.property)
+
+ if (isChecked == '0' || isChecked == 'false')
+ isChecked = false
+
+ $(this.selector).prop(checked, isChecked)
+ }
+
InspectorEditorCheckbox.prototype.focus = function() {
$(this.selector).closest('div').focus()
}
@@ -576,7 +780,7 @@
custom-checkbox nolabel"> \
\
+ id="{{cbId}}"/> \
\
\
\
@@ -594,6 +798,7 @@
this.editorId = editorId
this.selector = '#'+this.editorId+' select'
this.dynamicOptions = this.fieldDef.options ? false : true
+ this.initialization = false
var self = this
@@ -603,7 +808,7 @@
}
InspectorEditorDropdown.prototype.applyValue = function() {
- this.inspector.writeProperty(this.fieldDef.property, $(this.selector).val())
+ this.inspector.writeProperty(this.fieldDef.property, $(this.selector).val(), this.initialization)
}
InspectorEditorDropdown.prototype.renderEditor = function() {
@@ -678,7 +883,7 @@
this.indicatorContainer.addClass('loading-indicator-container').addClass('size-small').addClass('transparent')
}
- this.loadOptions()
+ this.loadOptions(true)
}
if (this.fieldDef.depends)
@@ -721,7 +926,7 @@
this.indicatorContainer.loadIndicator('hide')
}
- InspectorEditorDropdown.prototype.loadOptions = function() {
+ InspectorEditorDropdown.prototype.loadOptions = function(initialization) {
var $form = $(this.selector).closest('form'),
data = this.inspector.propertyValues,
$select = $(this.selector),
@@ -755,7 +960,9 @@
else
$('option:first-child', $select).attr("selected", "selected");
+ self.initialization = initialization
$select.trigger('change')
+ self.initialization = false
self.hideLoadingIndicator()
},
diff --git a/modules/backend/assets/less/controls/inspector.less b/modules/backend/assets/less/controls/inspector.less
index 2a2b94622..15cea3c08 100644
--- a/modules/backend/assets/less/controls/inspector.less
+++ b/modules/backend/assets/less/controls/inspector.less
@@ -90,6 +90,92 @@
select {
width: 90%;
}
+
+ div.external-param-editor-container {
+ position: relative;
+ padding-right: 30px;
+
+ div.external-editor {
+ bottom: 0;
+ margin: -5px -12px;
+ right: 30px;
+ left: auto;
+ top: 0;
+ position: absolute;
+
+ .transition(left 0.2s);
+ .transform( ~'translateZ(0)');
+ will-change: transform;
+
+ div.controls {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ left: 0;
+ top: 0;
+
+ a {
+ position: absolute;
+ left: 0;
+ top: 0;
+ display: inline-block;
+ height: 100%;
+ width: 30px;
+ color: #2b3e50;
+ outline: none;
+
+ i {
+ display: inline-block;
+ position: relative;
+ left: 10px;
+ top: 4px;
+ font-size: 15px;
+ }
+ }
+
+ input {
+ position: absolute;
+ display: block;
+ border: none;
+ width: 100%;
+ height: 100%;
+ left: 0;
+ top: 0;
+ padding-left: 30px;
+ padding-right: 12px;
+ background: transparent;
+ }
+ }
+ }
+
+ &.editor-visible {
+ div.external-editor {
+ div.controls {
+ input {
+ background: @color-inspector-bg;
+ }
+ }
+ }
+ }
+ }
+
+ &.active {
+ div.external-param-editor-container {
+ div.external-editor {
+ div.controls {
+ input {
+ background: white;
+ }
+ }
+ }
+ }
+ }
+
+ &.dropdown div.external-param-editor-container div.external-editor {
+ height: 100%;
+ margin: 0;
+ bottom: auto;
+ }
}
th {
diff --git a/modules/cms/assets/js/october.cmspage.js b/modules/cms/assets/js/october.cmspage.js
index 2a12c3f76..43bd96ef4 100644
--- a/modules/cms/assets/js/october.cmspage.js
+++ b/modules/cms/assets/js/october.cmspage.js
@@ -580,7 +580,7 @@
var $componentList = $('#cms-master-tabs > div.tab-content > .tab-pane.active .control-componentlist .layout')
if ($componentList.length == 0) {
- alert('Components can be added only to pages and layouts.')
+ alert('Components can be added only to pages, partials and layouts.')
return;
}
diff --git a/modules/cms/classes/ComponentBase.php b/modules/cms/classes/ComponentBase.php
index 67e3a705b..b6a6be477 100644
--- a/modules/cms/classes/ComponentBase.php
+++ b/modules/cms/classes/ComponentBase.php
@@ -183,36 +183,4 @@ abstract class ComponentBase extends Extendable
return $value;
}
-
- /**
- * Creates a page link to another page. Allows mapping to the other page's
- * component properties for the purpose of extracting URL routing parameters.
- * @param string $page Page name or page file name
- * @param string $class Component class name
- * @param array $mappings ['componentProperty' => 'routed value']
- * @return string
- */
- // protected function makePageLink($page, $class, $mappings = [])
- // {
- // if (!isset($this->pageLinkCache[$page.$class])) {
- // $this->pageLinkCache[$page.$class] = $this->getOtherPageComponent($page, $class);
- // }
-
- // if (!$component = $this->pageLinkCache[$page.$class])
- // return null;
-
- // $params = [];
- // foreach ($mappings as $property => $value) {
-
- // if (!$param = $component->property($property))
- // continue;
-
- // if (substr($param, 0, 1) == ':')
- // $param = substr($param, 1);
-
- // $params[$param] = $value;
- // }
-
- // return $this->pageUrl($page, $params);
- // }
}
diff --git a/modules/cms/classes/ComponentHelpers.php b/modules/cms/classes/ComponentHelpers.php
index 101eca678..b65e4c95e 100644
--- a/modules/cms/classes/ComponentHelpers.php
+++ b/modules/cms/classes/ComponentHelpers.php
@@ -20,12 +20,13 @@ class ComponentHelpers
$result = [];
$property = [
- 'property' => 'oc.alias',
- 'title' => Lang::get('cms::lang.component.alias'),
- 'description' => Lang::get('cms::lang.component.alias_description'),
- 'type' => 'string',
- 'validationPattern' => '^[a-zA-Z]+[0-9a-z\_]*$',
- 'validationMessage' => Lang::get('cms::lang.component.validation_message')
+ 'property' => 'oc.alias',
+ 'title' => Lang::get('cms::lang.component.alias'),
+ 'description' => Lang::get('cms::lang.component.alias_description'),
+ 'type' => 'string',
+ 'validationPattern' => '^[a-zA-Z]+[0-9a-z\_]*$',
+ 'validationMessage' => Lang::get('cms::lang.component.validation_message'),
+ 'noExternalParameter' => true
];
$result[] = $property;
diff --git a/modules/cms/classes/Controller.php b/modules/cms/classes/Controller.php
index a1246fdd1..907382369 100644
--- a/modules/cms/classes/Controller.php
+++ b/modules/cms/classes/Controller.php
@@ -100,6 +100,8 @@ class Controller extends BaseController
protected static $instance = null;
+ protected $partialComponentStack = [];
+
/**
* Creates the controller.
* @param \Cms\Classes\Theme $theme Specifies the CMS theme.
@@ -391,6 +393,8 @@ class Controller extends BaseController
{
$manager = ComponentManager::instance();
+ $properties = $this->setComponentPropertiesFromParameters($properties, []);
+
if ($addToLayout) {
if (!$componentObj = $manager->makeComponent($name, $this->layoutObj, $properties)) {
throw new CmsException(Lang::get('cms::lang.component.not_found', ['name'=>$name]));
@@ -664,6 +668,8 @@ class Controller extends BaseController
*/
public function renderPartial($name, $parameters = [], $throwException = true)
{
+ $vars = $this->vars;
+
/*
* Alias @ symbol for ::
*/
@@ -748,12 +754,63 @@ class Controller extends BaseController
}
}
+ /*
+ * Run partial functions (only for real partials)
+ */
+
+ if ($partial instanceof \Cms\Classes\Partial) {
+ $manager = ComponentManager::instance();
+
+ foreach ($partial->settings['components'] as $component => $properties) {
+ list($name, $alias) = strpos($component, ' ') ?
+ explode(' ', $component) : array($component, $component);
+
+ $properties = $this->setComponentPropertiesFromParameters($properties, $parameters, []);
+
+ if (!$componentObj = $manager->makeComponent($name, $this->pageObj, $properties))
+ throw new CmsException(Lang::get('cms::lang.component.not_found', ['name'=>$name]));
+
+ $componentObj->alias = $alias;
+ $parameters[$alias] = $partial->components[$alias] = $componentObj;
+
+ array_push($this->partialComponentStack, [
+ 'name' => $alias,
+ 'obj' => $componentObj
+ ]);
+
+ $componentObj->init();
+ $componentObj->onInit(); // Deprecated: Remove ithis line if year >= 2015
+ }
+
+ CmsException::mask($this->page, 300);
+ $parser = new CodeParser($partial);
+ $partialObj = $parser->source($this->page, $this->layout, $this);
+ CmsException::unmask();
+
+ CmsException::mask($partial, 300);
+ $partialObj->onStart();
+ $partial->runComponents();
+ $partialObj->onEnd();
+ CmsException::unmask();
+ }
+
+ /*
+ * Render the parital
+ */
CmsException::mask($partial, 400);
$this->loader->setObject($partial);
$template = $this->twig->loadTemplate($partial->getFullPath());
- $result = $template->render(array_merge($this->vars, $parameters));
- CmsException::unmask();
+ $result = $template->render(array_merge($this->vars, $parameters));
+ CmsException::unmask($this->partialComponentStack);
+
+ if ($partial instanceof \Cms\Classes\Partial) {
+ if ($this->partialComponentStack) {
+ array_pop($this->partialComponentStack);
+ }
+ }
+
+ $this->vars = $vars;
$this->componentContext = null;
return $result;
}
@@ -961,6 +1018,11 @@ class Controller extends BaseController
return $this->layout->components[$name];
}
+ foreach ($this->partialComponentStack as $componentInfo) {
+ if ($componentInfo['name'] == $name)
+ return $componentInfo['obj'];
+ }
+
return null;
}
@@ -1017,50 +1079,32 @@ class Controller extends BaseController
}
/**
- * Creates a basic component object for another page, useful for extracting properties.
- * @param string $page Page name or page file name
- * @param string $class Component class name
- * @return ComponentBase
+ * Sets component property values from partial parameters.
+ * The property values should be defined as {{ param }}.
+ * @param array &$properties Specifies the component properties loaded from the partial.
+ * @param array $parameters Specifies the partial parameters.
+ * @return Returns updated properties.
*/
- // public function getOtherPageComponent($page, $class)
- // {
- // $class = Str::normalizeClassName($class);
- // $theme = $this->getTheme();
- // $manager = ComponentManager::instance();
- // $componentObj = new $class;
+ protected function setComponentPropertiesFromParameters(&$properties, $parameters)
+ {
+ $result = [];
- // if (($page = Page::loadCached($theme, $page)) && isset($page->settings['components'])) {
- // foreach ($page->settings['components'] as $component => $properties) {
- // list($name, $alias) = strpos($component, ' ') ?
- // explode(' ', $component) :
- // array($component, $component)
- // ;
- // if ($manager->resolve($name) == $class) {
- // $componentObj->setProperties($properties);
- // $componentObj->alias = $alias;
- // return $componentObj;
- // }
- // }
+ $routerParameters = $this->router->getParameters();
- // if (!isset($page->settings['layout']))
- // return null;
+ foreach ($properties as $propertyName=>$propertyValue) {
+ $matches = [];
+ if (preg_match('/^\{\{([^\}]+)\}\}$/', $propertyValue, $matches)) {
+ $paramName = trim($matches[1]);
- // $layout = $page->settings['layout'];
- // if (($layout = Layout::loadCached($theme, $layout)) && isset($layout->settings['components'])) {
- // foreach ($layout->settings['components'] as $component => $properties) {
- // list($name, $alias) = strpos($component, ' ') ?
- // explode(' ', $component) :
- // array($component, $component)
- // ;
- // if ($manager->resolve($name) == $class) {
- // $componentObj->setProperties($properties);
- // $componentObj->alias = $alias;
- // return $componentObj;
- // }
- // }
- // }
- // }
+ if ( substr($paramName, 0, 1) == ':' ) {
+ $paramName = substr($paramName, 1);
+ $result[$propertyName] = array_key_exists($paramName, $routerParameters) ? $routerParameters[$paramName] : null;
+ } else
+ $result[$propertyName] = array_key_exists($paramName, $parameters) ? $parameters[$paramName] : null;
+ } else
+ $result[$propertyName] = $propertyValue;
+ }
- // return null;
- // }
+ return $result;
+ }
}
diff --git a/modules/cms/classes/Partial.php b/modules/cms/classes/Partial.php
index 55549266f..690319e60 100644
--- a/modules/cms/classes/Partial.php
+++ b/modules/cms/classes/Partial.php
@@ -17,4 +17,13 @@ class Partial extends CmsCompoundObject
{
return 'partials';
}
+
+ /**
+ * Returns name of a PHP class to us a parent for the PHP class created for the object's PHP section.
+ * @return mixed Returns the class name or null.
+ */
+ public function getCodeClassParent()
+ {
+ return '\Cms\Classes\PartialCode';
+ }
}
diff --git a/modules/cms/classes/PartialCode.php b/modules/cms/classes/PartialCode.php
new file mode 100644
index 000000000..4f125efd1
--- /dev/null
+++ b/modules/cms/classes/PartialCode.php
@@ -0,0 +1,11 @@
+addJs('/modules/cms/assets/js/october.cmspage.js', 'core');
$this->addJs('/modules/cms/assets/js/october.dragcomponents.js', 'core');
$this->addJs('/modules/cms/assets/js/october.tokenexpander.js', 'core');
+ $this->addJs('/modules/backend/formwidgets/codeeditor/assets/js/codeeditor.js', 'core');
+
$this->addCss('/modules/cms/assets/css/october.components.css', 'core');
// Preload Ace editor modes explicitly, because they could be changed dynamically
diff --git a/modules/cms/controllers/index/_form_page.htm b/modules/cms/controllers/index/_form_page.htm
index b326b632d..07cad3fd1 100644
--- a/modules/cms/controllers/index/_form_page.htm
+++ b/modules/cms/controllers/index/_form_page.htm
@@ -1,8 +1,12 @@
-= Form::open([
- 'class' => 'layout',
- 'data-change-monitor' => 'true',
- 'data-window-close-confirm' => e(trans('backend::lang.form.confirm_tab_close'))
-]) ?>
+ 'layout',
+ 'data-change-monitor' => 'true',
+ 'data-window-close-confirm' => e(trans('backend::lang.form.confirm_tab_close')),
+ 'data-inspector-external-parameters' => true
+ ];
+
+echo Form::open($formConfig) ?>
= $form->render() ?>