Skip to content

Commit 9e4bca0

Browse files
committed
fix rendering action buttons in case the dataset contains non-numeric indices
1 parent c9a236d commit 9e4bca0

File tree

4 files changed

+95
-98
lines changed

4 files changed

+95
-98
lines changed

src/renderers/BaseRenderer.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,11 @@ protected function isAddButtonPositionRowBegin()
514514
return in_array(self::POS_ROW_BEGIN, $this->addButtonPosition);
515515
}
516516

517+
protected function isFixedNumberOfRows()
518+
{
519+
return $this->max === $this->min;
520+
}
521+
517522
private function prepareIndexPlaceholder()
518523
{
519524
$this->indexPlaceholder = 'multiple_index_' . $this->id;
@@ -579,4 +584,31 @@ public function isBootstrapTheme()
579584
return $this->theme === self::THEME_BS;
580585
}
581586

587+
protected function renderRows()
588+
{
589+
$rows = [];
590+
591+
$rowIndex = 0;
592+
if ($this->data) {
593+
foreach ($this->data as $index => $item) {
594+
if ($rowIndex <= $this->max) {
595+
$rows[] = $this->renderRowContent($index, $item, $rowIndex);
596+
} else {
597+
break;
598+
}
599+
$rowIndex++;
600+
}
601+
for (; $rowIndex < $this->min; $rowIndex++) {
602+
$rows[] = $this->renderRowContent($rowIndex, null, $rowIndex);
603+
}
604+
} elseif ($this->min > 0) {
605+
for (; $rowIndex < $this->min; $rowIndex++) {
606+
$rows[] = $this->renderRowContent($rowIndex, null, $rowIndex);
607+
}
608+
}
609+
610+
return $rows;
611+
}
612+
613+
abstract protected function renderRowContent($index = null, $item = null, $rowIndex = null);
582614
}

src/renderers/DivRenderer.php

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -98,27 +98,7 @@ public function renderFooter()
9898
*/
9999
protected function renderBody()
100100
{
101-
$rows = [];
102-
103-
if ($this->data) {
104-
$j = 0;
105-
foreach ($this->data as $index => $item) {
106-
if ($j++ <= $this->max) {
107-
$rows[] = $this->renderRowContent($index, $item);
108-
} else {
109-
break;
110-
}
111-
}
112-
for ($i = $j; $i < $this->min; $i++) {
113-
$rows[] = $this->renderRowContent($i);
114-
}
115-
} elseif ($this->min > 0) {
116-
for ($i = 0; $i < $this->min; $i++) {
117-
$rows[] = $this->renderRowContent($i);
118-
}
119-
}
120-
121-
return implode("\n", $rows);
101+
return implode("\n", $this->renderRows());
122102
}
123103

124104
/**
@@ -128,14 +108,16 @@ protected function renderBody()
128108
* @param ActiveRecordInterface|array $item
129109
* @return mixed
130110
*/
131-
private function renderRowContent($index = null, $item = null)
111+
protected function renderRowContent($index = null, $item = null, $rowIndex = null)
132112
{
133113
$elements = [];
114+
134115
$columnIndex = 0;
135116
foreach ($this->columns as $column) {
136117
/* @var $column BaseColumn */
137118
$column->setModel($item);
138-
$elements[] = $this->renderCellContent($column, $index, $columnIndex++);
119+
$elements[] = $this->renderCellContent($column, $index, $columnIndex, $rowIndex);
120+
$columnIndex++;
139121
}
140122

141123
$content = Html::tag('div', implode("\n", $elements), $this->prepareRowOptions($index, $item));
@@ -174,10 +156,11 @@ protected function prepareRowOptions($index, $item)
174156
* @param BaseColumn $column
175157
* @param int|null $index
176158
* @param int|null $columnIndex
159+
* @param int|null $rowIndex
177160
* @return string
178161
* @throws \Exception
179162
*/
180-
public function renderCellContent($column, $index, $columnIndex = null)
163+
public function renderCellContent($column, $index = null, $columnIndex = null, $rowIndex = null)
181164
{
182165
$id = $column->getElementId($index);
183166
$name = $column->getElementName($index);
@@ -263,9 +246,10 @@ public function renderCellContent($column, $index, $columnIndex = null)
263246

264247
// first line
265248
if ($columnIndex == 0) {
266-
if ($this->max !== $this->min) {
267-
$content .= $this->renderActionColumn($index);
249+
if (!$this->isFixedNumberOfRows()) {
250+
$content .= $this->renderActionColumn($index, $column->getModel(), $rowIndex);
268251
}
252+
269253
if ($this->cloneButton) {
270254
$content .= $this->renderCloneColumn();
271255
}
@@ -287,14 +271,15 @@ public function renderCellContent($column, $index, $columnIndex = null)
287271
* @param null|ActiveRecordInterface|array $item
288272
* @return string
289273
*/
290-
private function renderActionColumn($index = null, $item = null)
274+
private function renderActionColumn($index = null, $item = null, $rowIndex = null)
291275
{
292-
$content = $this->getActionButton($index) . $this->getExtraButtons($index, $item);
276+
$content = $this->getActionButton($index, $rowIndex) . $this->getExtraButtons($index, $item);
293277

294278
$options = ['class' => 'list-cell__button'];
295279
$layoutConfig = array_merge([
296280
'buttonActionClass' => $this->isBootstrapTheme() ? 'col-sm-offset-0 col-sm-2' : '',
297281
], $this->layoutConfig);
282+
298283
Html::addCssClass($options, $layoutConfig['buttonActionClass']);
299284

300285
return Html::tag('div', $content, $options);
@@ -317,18 +302,20 @@ private function renderCloneColumn()
317302
return Html::tag('div', $this->renderCloneButton(), $options);
318303
}
319304

320-
private function getActionButton($index)
305+
private function getActionButton($index, $rowIndex)
321306
{
322307
if ($index === null || $this->min === 0) {
323308
return $this->renderRemoveButton();
324309
}
325310

326-
$index++;
327-
if ($index < $this->min) {
311+
// rowIndex is zero-based, so we have to increment it to properly cpmpare it with min number of rows
312+
$rowIndex++;
313+
314+
if ($rowIndex < $this->min) {
328315
return '';
329316
}
330317

331-
if ($index === $this->min) {
318+
if ($rowIndex === $this->min) {
332319
return $this->isAddButtonPositionRow() ? $this->renderAddButton() : '';
333320
}
334321

src/renderers/ListRenderer.php

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -102,27 +102,7 @@ public function renderFooter()
102102
*/
103103
protected function renderBody()
104104
{
105-
$rows = [];
106-
107-
if ($this->data) {
108-
$j = 0;
109-
foreach ($this->data as $index => $item) {
110-
if ($j++ <= $this->max) {
111-
$rows[] = $this->renderRowContent($index, $item);
112-
} else {
113-
break;
114-
}
115-
}
116-
for ($i = $j; $i < $this->min; $i++) {
117-
$rows[] = $this->renderRowContent($i);
118-
}
119-
} elseif ($this->min > 0) {
120-
for ($i = 0; $i < $this->min; $i++) {
121-
$rows[] = $this->renderRowContent($i);
122-
}
123-
}
124-
125-
return Html::tag('tbody', implode("\n", $rows));
105+
return Html::tag('tbody', implode("\n", $this->renderRows()));
126106
}
127107

128108
/**
@@ -133,7 +113,7 @@ protected function renderBody()
133113
* @return mixed
134114
* @throws InvalidConfigException
135115
*/
136-
private function renderRowContent($index = null, $item = null)
116+
protected function renderRowContent($index = null, $item = null, $rowIndex = null)
137117
{
138118
$elements = [];
139119

@@ -146,8 +126,8 @@ private function renderRowContent($index = null, $item = null)
146126

147127
$content = [];
148128
$content[] = Html::tag('td', implode("\n", $elements));
149-
if ($this->max !== $this->min) {
150-
$content[] = $this->renderActionColumn($index);
129+
if (!$this->isFixedNumberOfRows()) {
130+
$content[] = $this->renderActionColumn($index, $item, $rowIndex);
151131
}
152132

153133
if ($this->cloneButton) {
@@ -290,12 +270,13 @@ public function renderCellContent($column, $index, $columnIndex = null)
290270
*
291271
* @param null|int $index
292272
* @param null|ActiveRecordInterface|array $item
273+
* @param null|int $rowIndex
293274
* @return string
294275
* @throws \Exception
295276
*/
296-
private function renderActionColumn($index = null, $item = null)
277+
private function renderActionColumn($index = null, $item = null, $rowIndex = null)
297278
{
298-
$content = $this->getActionButton($index) . $this->getExtraButtons($index, $item);
279+
$content = $this->getActionButton($index, $rowIndex) . $this->getExtraButtons($index, $item);
299280

300281
return Html::tag('td', $content, [
301282
'class' => 'list-cell__button',
@@ -315,18 +296,20 @@ private function renderCloneColumn()
315296
]);
316297
}
317298

318-
private function getActionButton($index)
299+
private function getActionButton($index, $rowIndex)
319300
{
320301
if ($index === null || $this->min === 0) {
321302
return $this->renderRemoveButton();
322303
}
323304

324-
$index++;
325-
if ($index < $this->min) {
305+
// rowIndex is zero-based, so we have to increment it to properly cpmpare it with min number of rows
306+
$rowIndex++;
307+
308+
if ($rowIndex < $this->min) {
326309
return '';
327310
}
328311

329-
if ($index === $this->min) {
312+
if ($rowIndex === $this->min) {
330313
return $this->isAddButtonPositionRow() ? $this->renderAddButton() : '';
331314
}
332315

src/renderers/TableRenderer.php

Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -167,27 +167,7 @@ private function renderButtonHeaderCell($button = '')
167167
*/
168168
protected function renderBody()
169169
{
170-
$rows = [];
171-
172-
if ($this->data) {
173-
$j = 0;
174-
foreach ($this->data as $index => $item) {
175-
if ($j++ <= $this->max) {
176-
$rows[] = $this->renderRowContent($index, $item);
177-
} else {
178-
break;
179-
}
180-
}
181-
for ($i = $j; $i < $this->min; $i++) {
182-
$rows[] = $this->renderRowContent($i);
183-
}
184-
} elseif ($this->min > 0) {
185-
for ($i = 0; $i < $this->min; $i++) {
186-
$rows[] = $this->renderRowContent($i);
187-
}
188-
}
189-
190-
return Html::tag('tbody', implode("\n", $rows));
170+
return Html::tag('tbody', implode("\n", $this->renderRows()));
191171
}
192172

193173
/**
@@ -198,13 +178,13 @@ protected function renderBody()
198178
* @return mixed
199179
* @throws InvalidConfigException
200180
*/
201-
private function renderRowContent($index = null, $item = null)
181+
protected function renderRowContent($index = null, $item = null, $rowIndex = null)
202182
{
203183
$cells = [];
204184
$hiddenInputs = [];
205-
$isLastRow = $this->max === $this->min;
206-
if (!$isLastRow && $this->isAddButtonPositionRowBegin()) {
207-
$cells[] = $this->renderActionColumn($index, $item, true);
185+
186+
if (!$this->isFixedNumberOfRows() && $this->isAddButtonPositionRowBegin()) {
187+
$cells[] = $this->renderActionColumn($index, $item, $rowIndex, true);
208188
}
209189

210190
$columnIndex = 0;
@@ -217,12 +197,13 @@ private function renderRowContent($index = null, $item = null)
217197
$cells[] = $this->renderCellContent($column, $index, $columnIndex++);
218198
}
219199
}
200+
220201
if ($this->cloneButton) {
221202
$cells[] = $this->renderCloneColumn();
222203
}
223204

224-
if (!$isLastRow) {
225-
$cells[] = $this->renderActionColumn($index, $item);
205+
if (!$this->isFixedNumberOfRows()) {
206+
$cells[] = $this->renderActionColumn($index, $item, $rowIndex);
226207
}
227208

228209
if ($hiddenInputs) {
@@ -268,6 +249,8 @@ protected function prepareRowOptions($index, $item)
268249
* @param int|null $index
269250
* @param int|null $columnIndex
270251
* @return string
252+
*
253+
* @todo rethink visibility level (make it private)
271254
*/
272255
public function renderCellContent($column, $index, $columnIndex = null)
273256
{
@@ -284,7 +267,6 @@ public function renderCellContent($column, $index, $columnIndex = null)
284267
$options = ArrayHelper::merge($options, ['class' => $this->iconMap['drag-handle']]);
285268
}
286269

287-
288270
$input = $column->renderInput($name, $options, [
289271
'id' => $id,
290272
'name' => $name,
@@ -336,14 +318,19 @@ public function renderCellContent($column, $index, $columnIndex = null)
336318
/**
337319
* Renders the action column.
338320
*
339-
* @param null|int $index
321+
* @param null|int|string $index
340322
* @param null|ActiveRecordInterface|array $item
341-
* @param bool $isFirstColumn
323+
* @param int $rowIndex
342324
* @return string
343325
*/
344-
private function renderActionColumn($index = null, $item = null, $isFirstColumn = false)
326+
private function renderActionColumn(
327+
$index = null,
328+
$item = null,
329+
$rowIndex = null,
330+
$isFirstColumn = false
331+
)
345332
{
346-
$content = $this->getActionButton($index, $isFirstColumn) . $this->getExtraButtons($index, $item);
333+
$content = $this->getActionButton($index, $rowIndex, $isFirstColumn) . $this->getExtraButtons($index, $item);
347334

348335
return Html::tag('td', $content, [
349336
'class' => 'list-cell__button',
@@ -362,7 +349,12 @@ private function renderCloneColumn()
362349
]);
363350
}
364351

365-
private function getActionButton($index, $isFirstColumn)
352+
/**
353+
* @param int|string|null $index
354+
* @param int $rowIndex
355+
* @return string
356+
*/
357+
private function getActionButton($index = null, $rowIndex = null, $isFirstColumn = false)
366358
{
367359
if ($index === null || $this->min === 0) {
368360
if ($isFirstColumn) {
@@ -372,16 +364,19 @@ private function getActionButton($index, $isFirstColumn)
372364
return $this->isAddButtonPositionRowBegin() ? '' : $this->renderRemoveButton();
373365
}
374366

375-
$index++;
376-
if ($index < $this->min) {
367+
// rowIndex is zero-based, so we have to increment it to properly cpmpare it with min number of rows
368+
$rowIndex++;
369+
370+
if ($rowIndex < $this->min) {
377371
return '';
378372
}
379373

380-
if ($index === $this->min) {
374+
if ($rowIndex === $this->min) {
381375
if ($isFirstColumn) {
382376
return $this->isAddButtonPositionRowBegin() ? $this->renderAddButton() : '';
383377
}
384378

379+
385380
return $this->isAddButtonPositionRow() ? $this->renderAddButton() : '';
386381
}
387382

0 commit comments

Comments
 (0)