mirror of
https://github.com/wintercms/winter.git
synced 2024-06-28 05:33:29 +02:00
Added lazy loading for backend form tabs (#4658)
* Added lazy loading for backend form tabs
This commit is contained in:
parent
9b77e8d81a
commit
4704f85096
@ -27,6 +27,11 @@ class FormTabs implements IteratorAggregate, ArrayAccess
|
||||
*/
|
||||
public $fields = [];
|
||||
|
||||
/**
|
||||
* @var array Names of tabs to lazy load.
|
||||
*/
|
||||
public $lazy = [];
|
||||
|
||||
/**
|
||||
* @var string Default tab label to use when none is specified.
|
||||
*/
|
||||
@ -106,6 +111,10 @@ class FormTabs implements IteratorAggregate, ArrayAccess
|
||||
if (array_key_exists('paneCssClass', $config)) {
|
||||
$this->paneCssClass = $config['paneCssClass'];
|
||||
}
|
||||
|
||||
if (array_key_exists('lazy', $config)) {
|
||||
$this->lazy = $config['lazy'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -456,6 +456,35 @@ class Form extends WidgetBase
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders all fields of a tab in the target tab-pane.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function onLazyLoadTab()
|
||||
{
|
||||
$target = post('target');
|
||||
$tabName = post('name');
|
||||
|
||||
$fields = array_get(optional($this->getTab('primary'))->fields, $tabName);
|
||||
|
||||
return [
|
||||
$target => $this->makePartial('form_fields', ['fields' => $fields]),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to convert a field name to a valid ID attribute.
|
||||
*
|
||||
* @param $input
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function nameToId($input)
|
||||
{
|
||||
return HtmlHelper::nameToId($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a flat array of form fields from the configuration.
|
||||
* Also slots fields in to their respective tabs.
|
||||
@ -935,7 +964,7 @@ class Form extends WidgetBase
|
||||
}
|
||||
|
||||
$widgetConfig = $this->makeConfig($field->config);
|
||||
$widgetConfig->alias = $this->alias . studly_case(HtmlHelper::nameToId($field->fieldName));
|
||||
$widgetConfig->alias = $this->alias . studly_case($this->nameToId($field->fieldName));
|
||||
$widgetConfig->sessionKey = $this->getSessionKey();
|
||||
$widgetConfig->previewMode = $this->previewMode;
|
||||
$widgetConfig->model = $this->model;
|
||||
|
@ -34,6 +34,7 @@
|
||||
this.bindDependants()
|
||||
this.bindCheckboxlist()
|
||||
this.toggleEmptyTabs()
|
||||
this.bindLazyTabs()
|
||||
this.bindCollapsibleSections()
|
||||
|
||||
this.$el.on('oc.triggerOn.afterUpdate', this.proxy(this.toggleEmptyTabs))
|
||||
@ -161,6 +162,34 @@
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* Render tab form fields once a lazy tab is selected.
|
||||
*/
|
||||
FormWidget.prototype.bindLazyTabs = function() {
|
||||
this.$el.on('click', '.tab-lazy [data-toggle="tab"]', function() {
|
||||
var $el = $(this)
|
||||
$.request('form::onLazyLoadTab', {
|
||||
data: {
|
||||
target: $el.data('target'),
|
||||
name: $el.data('tab-name'),
|
||||
},
|
||||
success: function(data) {
|
||||
this.success(data)
|
||||
$el.parent().removeClass('tab-lazy')
|
||||
// Trigger all input presets to populate new fields.
|
||||
setTimeout(function() {
|
||||
$('[data-input-preset]').each(function() {
|
||||
var preset = $(this).data('oc.inputPreset')
|
||||
if (preset && preset.$src) {
|
||||
preset.$src.trigger('input')
|
||||
}
|
||||
})
|
||||
}, 0)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* Hides tabs that have no content, it is possible this can be
|
||||
* called multiple times in a single cycle due to input.trigger.
|
||||
@ -184,7 +213,7 @@
|
||||
/*
|
||||
* Check each tab pane for form field groups
|
||||
*/
|
||||
$('.tab-pane', tabControl).each(function() {
|
||||
$('.tab-pane:not(.lazy)', tabControl).each(function() {
|
||||
$('[data-target="#' + $(this).attr('id') + '"]', tabControl)
|
||||
.closest('li')
|
||||
.toggle(!!$('> .form-group:not(:empty):not(.hide)', $(this)).length)
|
||||
|
@ -14,7 +14,10 @@
|
||||
<div class="<?= $navCss ?>">
|
||||
<ul class="nav nav-tabs">
|
||||
<?php $index = 0; foreach ($tabs as $name => $fields): ?>
|
||||
<li class="<?= $index++ == 0 ? 'active' : '' ?>">
|
||||
<?php
|
||||
$lazy = in_array($name, $tabs->lazy);
|
||||
?>
|
||||
<li class="<?= ($index++ === 0) ? 'active' : '' ?> <?= $lazy ? 'tab-lazy' : '' ?>">
|
||||
<a href="#<?= $type . 'tab-' . $index ?>">
|
||||
<span class="title">
|
||||
<span>
|
||||
@ -29,11 +32,19 @@
|
||||
</div>
|
||||
|
||||
<div class="tab-content <?= $contentCss ?>">
|
||||
<?php $index = 0; foreach ($tabs as $name => $fields): ?>
|
||||
<div
|
||||
class="tab-pane <?= e($tabs->getPaneCssClass($index, $name)) ?> <?= $index++ == 0 ? 'active' : '' ?> <?= $paneCss ?>"
|
||||
id="<?= $type . 'tab-' . $index ?>">
|
||||
<?= $this->makePartial('form_fields', ['fields' => $fields]) ?>
|
||||
</div>
|
||||
<?php
|
||||
$index = 0;
|
||||
foreach ($tabs as $name => $fields):
|
||||
$lazy = in_array($name, $tabs->lazy);
|
||||
?>
|
||||
<div
|
||||
class="tab-pane <?= $lazy ? 'lazy' : '' ?> <?= e($tabs->getPaneCssClass($index, $name)) ?> <?= ($index++ === 0) ? 'active' : '' ?> <?= $paneCss ?>"
|
||||
id="<?= $type . 'tab-' . $index ?>">
|
||||
<?php if ($lazy): ?>
|
||||
<?= $this->makePartial('form_tabs_lazy', ['fields' => $fields]) ?>
|
||||
<?php else: ?>
|
||||
<?= $this->makePartial('form_fields', ['fields' => $fields]) ?>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
|
33
modules/backend/widgets/form/partials/_form_tabs_lazy.htm
Normal file
33
modules/backend/widgets/form/partials/_form_tabs_lazy.htm
Normal file
@ -0,0 +1,33 @@
|
||||
<div class="loading-indicator-container m-t">
|
||||
<div class="loading-indicator indicator-center">
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
// Do not create a hidden field for these field types since
|
||||
// they don't contain any form data.
|
||||
$ignoredTypes = ['section', 'partial'];
|
||||
|
||||
foreach ($fields as $field):
|
||||
if (in_array($field->type, $ignoredTypes)) continue;
|
||||
|
||||
$isMultiValue = is_array($field->value);
|
||||
foreach (array_wrap($field->value) as $index => $value):
|
||||
// Use array field names if the field has multiple values (repeater, checkboxlist, etc.).
|
||||
$fieldName = $isMultiValue ? sprintf('%s[%s]', $field->getName(), $index) : $field->getName();
|
||||
|
||||
$valueIsArray = is_array($value);
|
||||
foreach (array_wrap($value) as $index => $value):
|
||||
// Set the correct array keys if the value is an array (repeater form fields).
|
||||
$currentFieldName = $valueIsArray ? sprintf('%s[%s]', $fieldName, $index) : $fieldName;
|
||||
?>
|
||||
<input
|
||||
type="hidden"
|
||||
name="<?= $currentFieldName ?>"
|
||||
id="<?= $this->nameToId($currentFieldName) ?>"
|
||||
value="<?= e($value) ?>"
|
||||
<?= $field->getAttributes() ?>
|
||||
/>
|
||||
<?php endforeach ?>
|
||||
<?php endforeach ?>
|
||||
<?php endforeach ?>
|
Loading…
x
Reference in New Issue
Block a user