Skip to content

Commit e962daa

Browse files
committed
#79 Embedded multiple input [WIP]
1 parent c9b394c commit e962daa

File tree

12 files changed

+291
-39
lines changed

12 files changed

+291
-39
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace unclead\widgets\examples\actions;
4+
5+
use Yii;
6+
use yii\base\Action;
7+
use yii\bootstrap\ActiveForm;
8+
use yii\web\Response;
9+
use unclead\widgets\examples\models\ExampleModel;
10+
11+
/**
12+
* Class EmbeddedInputAction
13+
* @package unclead\widgets\examples\actions
14+
*/
15+
class EmbeddedInputAction extends Action
16+
{
17+
public function run()
18+
{
19+
Yii::setAlias('@unclead-examples', realpath(__DIR__ . '/../'));
20+
21+
$model = new ExampleModel();
22+
23+
$request = Yii::$app->getRequest();
24+
if ($request->isPost && $request->post('ajax') !== null) {
25+
$model->load(Yii::$app->request->post());
26+
Yii::$app->response->format = Response::FORMAT_JSON;
27+
$result = ActiveForm::validate($model);
28+
return $result;
29+
}
30+
31+
if ($model->load(Yii::$app->request->post())) {
32+
if (!$model->validate()) {
33+
Yii::error('Validation errors: ' . print_r($model->getErrors(), true));
34+
}
35+
}
36+
37+
return $this->controller->render('@unclead-examples/views/embedded-input.php', ['model' => $model]);
38+
}
39+
}

examples/models/ExampleModel.php

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace unclead\widgets\examples\models;
44

55
use yii\base\Model;
6+
use yii\helpers\ArrayHelper;
67
use yii\validators\EmailValidator;
78
use yii\validators\NumberValidator;
89
use yii\validators\RequiredValidator;
@@ -41,6 +42,11 @@ class ExampleModel extends Model
4142
*/
4243
public $title;
4344

45+
/**
46+
* @var array
47+
*/
48+
public $questions;
49+
4450
public function init()
4551
{
4652
parent::init();
@@ -64,6 +70,22 @@ public function init()
6470
'enable' => 0
6571
],
6672
];
73+
74+
$this->questions = [
75+
[
76+
'question' => 'test1',
77+
'answers' => [
78+
[
79+
'right' => 0,
80+
'answer' => 'test1'
81+
],
82+
[
83+
'right' => 1,
84+
'answer' => 'test2'
85+
]
86+
]
87+
]
88+
];
6789
}
6890

6991

@@ -73,7 +95,8 @@ public function rules()
7395
['title', 'required'],
7496
['emails', 'validateEmails'],
7597
['phones', 'validatePhones'],
76-
['schedule', 'validateSchedule']
98+
['schedule', 'validateSchedule'],
99+
['questions', 'validateQuestions']
77100
];
78101
}
79102

@@ -83,14 +106,15 @@ public function attributes()
83106
'emails',
84107
'phones',
85108
'title',
86-
'schedule'
109+
'schedule',
110+
'questions'
87111
];
88112
}
89113

90114
public function scenarios()
91115
{
92116
return [
93-
self::SCENARIO_DEFAULT => ['emails', 'phones', 'schedule', 'title']
117+
self::SCENARIO_DEFAULT => $this->attributes()
94118
];
95119
}
96120

@@ -165,4 +189,41 @@ public function validateSchedule($attribute)
165189
}
166190
}
167191
}
192+
193+
public function validateQuestions($attribute)
194+
{
195+
foreach($this->$attribute as $questionIndex => $question) {
196+
$this->internalValidateQuestion($questionIndex, $question);
197+
$this->internalValidateAnswers($questionIndex, $question['answers']);
198+
}
199+
}
200+
201+
private function internalValidateQuestion($questionIndex, $question)
202+
{
203+
$requiredValidator = new RequiredValidator();
204+
$error = null;
205+
206+
$value = ArrayHelper::getValue($question, 'question', null);
207+
$requiredValidator->validate($value, $error);
208+
if (!empty($error)) {
209+
$key = sprintf('questions[%d][question]', $questionIndex);
210+
$this->addError($key, $error);
211+
}
212+
}
213+
214+
private function internalValidateAnswers($questionIndex, $answers)
215+
{
216+
$requiredValidator = new RequiredValidator();
217+
$error = null;
218+
219+
foreach ($answers as $answerIndex => $answer) {
220+
$error = null;
221+
$value = ArrayHelper::getValue($answer, 'answer', null);
222+
$requiredValidator->validate($value, $error);
223+
if (!empty($error)) {
224+
$key = sprintf('questions[%d][answers][%d][answer]', $questionIndex, $answerIndex);
225+
$this->addError($key, $error);
226+
}
227+
}
228+
}
168229
}

examples/views/embedded-input.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
use yii\bootstrap\ActiveForm;
4+
use unclead\widgets\MultipleInput;
5+
use unclead\widgets\examples\models\ExampleModel;
6+
use yii\helpers\Html;
7+
use unclead\widgets\MultipleInputColumn;
8+
9+
10+
/* @var $this \yii\web\View */
11+
/* @var $model ExampleModel */
12+
13+
$commonAttributeOptions = [
14+
'enableAjaxValidation' => false,
15+
'enableClientValidation' => false,
16+
'validateOnChange' => false,
17+
'validateOnSubmit' => true,
18+
'validateOnBlur' => false,
19+
];
20+
?>
21+
22+
<?php $form = ActiveForm::begin([
23+
'enableAjaxValidation' => true,
24+
'enableClientValidation' => false,
25+
'validateOnChange' => false,
26+
'validateOnSubmit' => true,
27+
'validateOnBlur' => false,
28+
]);?>
29+
30+
<?php
31+
32+
echo MultipleInput::widget([
33+
'model' => $model,
34+
'attribute' => 'questions',
35+
'attributeOptions' => $commonAttributeOptions,
36+
'columns' => [
37+
[
38+
'name' => 'question',
39+
'type' => 'textarea',
40+
],
41+
[
42+
'name' => 'answers',
43+
'type' => MultipleInput::class,
44+
'options' => [
45+
'attributeOptions' => $commonAttributeOptions,
46+
'columns' => [
47+
[
48+
'name' => 'right',
49+
'type' => MultipleInputColumn::TYPE_CHECKBOX
50+
],
51+
[
52+
'name' => 'answer'
53+
]
54+
]
55+
]
56+
]
57+
],
58+
]);
59+
?>
60+
61+
<?= Html::submitButton('Update', ['class' => 'btn btn-success']);?>
62+
<?php ActiveForm::end();?>

examples/views/multiple-input.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
?>
1515

1616
<?php $form = ActiveForm::begin([
17-
'enableAjaxValidation' => true,
17+
'enableAjaxValidation' => false,
1818
'enableClientValidation' => false,
1919
'validateOnChange' => false,
2020
'validateOnSubmit' => true,
@@ -24,17 +24,25 @@
2424
<h3>Single column</h3>
2525
<?php
2626
echo $form->field($model, 'emails')->widget(MultipleInput::className(), [
27-
'limit' => 6,
28-
'allowEmptyList' => false,
29-
'enableGuessTitle' => true,
30-
'min' => 2, // should be at least 2 rows
27+
'limit' => 6,
28+
'allowEmptyList' => false,
29+
'columns' => [
30+
[
31+
'name' => 'emails',
32+
'options' => [
33+
'placeholder' => 'E-mail'
34+
]
35+
]
36+
],
37+
'min' => 2, // should be at least 2 rows
3138
'addButtonPosition' => MultipleInput::POS_HEADER // show add button in the header
3239
])
3340
->label(false);
3441
?>
3542

3643
<h3>Multiple columns</h3>
37-
<?= $form->field($model, 'schedule')->widget(MultipleInput::className(), [
44+
<?php
45+
echo $form->field($model, 'schedule')->widget(MultipleInput::className(), [
3846
'limit' => 4,
3947
'allowEmptyList' => true,
4048
'rowOptions' => function($model) {

src/MultipleInput.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,17 @@ public function init()
116116
*/
117117
protected function initData()
118118
{
119-
if (is_null($this->data) && $this->model instanceof Model) {
120-
foreach ((array) $this->model->{$this->attribute} as $index => $value) {
119+
if ($this->data !== null) {
120+
return;
121+
}
122+
123+
if ($this->value !== null) {
124+
$this->data = $this->value;
125+
return;
126+
}
127+
128+
if ($this->model instanceof Model) {
129+
foreach ((array)$this->model->{$this->attribute} as $index => $value) {
121130
$this->data[$index] = $value;
122131
}
123132
}

src/MultipleInputColumn.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public function init()
4747
public function getElementName($index, $withPrefix = true)
4848
{
4949
if (is_null($index)) {
50-
$index = '{multiple_index}';
50+
$index = '{' . $this->renderer->getIndexPlaceholder() . '}';
5151
}
5252

5353
$elementName = $this->isRendererHasOneColumn()

src/TabularColumn.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ class TabularColumn extends BaseColumn
2727
public function getElementName($index, $withPrefix = true)
2828
{
2929
if (is_null($index)) {
30-
$index = '{multiple_index}';
30+
$index = '{' . $this->renderer->getIndexPlaceholder() . '}';
3131
}
32+
3233
$elementName = '[' . $index . '][' . $this->name . ']';
3334
$prefix = $withPrefix ? $this->getModel()->formName() : '';
35+
3436
return $prefix . $elementName;
3537
}
3638

src/assets/src/css/multiple-input.css

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
width: 80%;
88
}
99

10-
.multiple-input-list.no-buttons
11-
.multiple-input-list__input {
10+
.multiple-input-list.no-buttons .multiple-input-list__input {
1211
display: block;
1312
width: 100%;
1413
}
@@ -44,4 +43,7 @@ table.multiple-input-list tr > th {
4443
.multiple-input-list__item .radio-list .radio,
4544
.multiple-input-list__item .checkbox-list .checkbox {
4645
margin: 0;
46+
}
47+
.multiple-input-list .multiple-input-list {
48+
margin-top: -5px;
4749
}

0 commit comments

Comments
 (0)