Implemented minItems repeater property on client & server

Also implemented maxItems on server (previously only client). Fixes https://github.com/octobercms/october/issues/3668
This commit is contained in:
Luke Towers 2018-08-12 01:33:51 -06:00
parent 6774920003
commit cbed54a263
4 changed files with 45 additions and 2 deletions

View File

@ -1,8 +1,9 @@
<?php namespace Backend\FormWidgets;
use Lang;
use ApplicationException;
use Backend\Classes\FormField;
use Backend\Classes\FormWidgetBase;
use ApplicationException;
/**
* Repeater Form Widget
@ -37,7 +38,12 @@ class Repeater extends FormWidgetBase
public $titleFrom = false;
/**
* @var int Maximum repeated items allowable.
* @var int Minimum items required. Pre-displays those items when not using groups
*/
public $minItems = null;
/**
* @var int Maximum items permitted
*/
public $maxItems = null;
@ -94,6 +100,7 @@ class Repeater extends FormWidgetBase
'prompt',
'sortable',
'titleFrom',
'minItems',
'maxItems',
]);
@ -144,6 +151,7 @@ class Repeater extends FormWidgetBase
$this->vars['prompt'] = $this->prompt;
$this->vars['formWidgets'] = $this->formWidgets;
$this->vars['titleFrom'] = $this->titleFrom;
$this->vars['minItems'] = $this->minItems;
$this->vars['maxItems'] = $this->maxItems;
$this->vars['useGroups'] = $this->useGroups;
@ -184,6 +192,13 @@ class Repeater extends FormWidgetBase
}
}
if ($this->minItems && count($value) < $this->minItems) {
throw new ApplicationException(Lang::get('backend::lang.repeater.min_items_failed', ['name' => $this->fieldName, 'min' => $this->minItems, 'items' => count($value)]));
}
if ($this->maxItems && count($value) > $this->maxItems) {
throw new ApplicationException(Lang::get('backend::lang.repeater.max_items_failed', ['name' => $this->fieldName, 'max' => $this->maxItems, 'items' => count($value)]));
}
return array_values($value);
}
@ -196,6 +211,21 @@ class Repeater extends FormWidgetBase
$loadedIndexes = $loadedGroups = [];
$loadValue = $this->getLoadValue();
// Ensure that the minimum number of items are preinitialized
// ONLY DONE WHEN NOT IN GROUP MODE
if (!$this->useGroups && $this->minItems > 0) {
if (!is_array($loadValue)) {
$loadValue = [];
for ($i = 0; $i < $this->minItems; $i++) {
$loadValue[$i] = [];
}
} elseif (count($loadValue) < $this->minItems) {
for ($i = 0; $i < ($this->minItems - count($loadValue)); $i++) {
$loadValue[] = [];
}
}
}
if (is_array($loadValue)) {
foreach ($loadValue as $index => $loadedValue) {
$loadedIndexes[] = $index;

View File

@ -34,6 +34,7 @@
sortableHandle: '.repeater-item-handle',
sortableContainer: 'ul.field-repeater-items',
titleFrom: null,
minItems: null,
maxItems: null
}
@ -122,6 +123,13 @@
}
Repeater.prototype.togglePrompt = function () {
if (this.options.minItems && this.options.minItems > 0) {
var repeatedItems = this.$el.find('> .field-repeater-items > .field-repeater-item').length,
$removeItemBtn = this.$el.find('> .field-repeater-items > .field-repeater-item > .repeater-item-remove')
$removeItemBtn.toggle(repeatedItems > this.options.minItems)
}
if (this.options.maxItems && this.options.maxItems > 0) {
var repeatedItems = this.$el.find('> .field-repeater-items > .field-repeater-item').length,
$addItemBtn = this.$el.find('> .field-repeater-add-item')

View File

@ -1,6 +1,7 @@
<div class="field-repeater"
data-control="fieldrepeater"
<?= $titleFrom ? 'data-title-from="'.$titleFrom.'"' : '' ?>
<?= $minItems ? 'data-min-items="'.$minItems.'"' : '' ?>
<?= $maxItems ? 'data-max-items="'.$maxItems.'"' : '' ?>
data-sortable-container="#<?= $this->getId('items') ?>"
data-sortable-handle=".<?= $this->getId('items') ?>-handle">

View File

@ -217,6 +217,10 @@ return [
'remove_confirm' => 'Are you sure?',
'remove_file' => 'Remove file'
],
'repeater' => [
'min_items_failed' => ':name requires a minimum of :min items, only :items were provided',
'max_items_failed' => ':name only allows up to :max items, :items were provided',
],
'form' => [
'create_title' => 'New :name',
'update_title' => 'Edit :name',