Skip to content

Commit 4206c37

Browse files
committed
Fixed ajax validation of radio/checkbox lists
1 parent d7d6586 commit 4206c37

File tree

4 files changed

+148
-80
lines changed

4 files changed

+148
-80
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Yii2 multiple input change log
55
---------------------
66

77
- Bug #61: Fixed a rendering of remove button
8+
- Bug #64 Radio/checkbox lists doesn't work correctly
89

910
1.2.10
1011
------

src/assets/src/js/jquery.multipleInput.js

Lines changed: 106 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,12 @@
8282

8383
$wrapper.on('click.multipleInput', '.js-input-remove', function (e) {
8484
e.preventDefault();
85-
methods.removeInput.apply(this);
85+
removeInput($(this));
8686
});
8787

8888
$wrapper.on('click.multipleInput', '.js-input-plus', function (e) {
8989
e.preventDefault();
90-
methods.addInput.apply(this);
90+
addInput($(this));
9191
});
9292

9393
var intervalID = setInterval(function(){
@@ -109,10 +109,11 @@
109109
attributeDefaults[key] = value;
110110
}
111111
});
112+
112113
$wrapper.data('multipleInput').attributeDefaults = attributeDefaults;
113114

114115
$wrapper.find('.multiple-input-list').find('input, select, textarea').each(function () {
115-
methods.addAttribute.apply(this);
116+
addAttribute($(this));
116117
});
117118
$wrapper.data('multipleInput').currentIndex = $wrapper.find('.multiple-input-list__item').length;
118119
clearInterval(intervalID);
@@ -121,95 +122,126 @@
121122
$wrapper.trigger(event);
122123
}
123124
}, 100);
124-
},
125+
}
126+
};
125127

126-
addInput: function () {
127-
var $wrapper = $(this).closest('.multiple-input').first(),
128-
data = $wrapper.data('multipleInput'),
129-
settings = data.settings,
130-
template = settings.template,
131-
inputList = $wrapper.find('.multiple-input-list').first(),
132-
count = $wrapper.find('.multiple-input-list__item').length;
128+
var addInput = function (btn) {
129+
var $wrapper = $(btn).closest('.multiple-input').first(),
130+
data = $wrapper.data('multipleInput'),
131+
settings = data.settings,
132+
template = settings.template,
133+
inputList = $wrapper.find('.multiple-input-list').first(),
134+
count = $wrapper.find('.multiple-input-list__item').length;
133135

134-
if (settings.limit != null && count >= settings.limit) {
135-
return;
136-
}
136+
if (settings.limit != null && count >= settings.limit) {
137+
return;
138+
}
137139

138-
template = template.replaceAll('{multiple_index}', data.currentIndex);
140+
template = template.replaceAll('{multiple_index}', data.currentIndex);
139141

140-
$(template).hide().appendTo(inputList).fadeIn(300);
142+
$(template).hide().appendTo(inputList).fadeIn(300);
141143

142-
$(template).find('input, select, textarea').each(function () {
143-
methods.addAttribute.apply(this);
144-
});
144+
$(template).find('input, select, textarea').each(function () {
145+
addAttribute($(this));
146+
});
145147

146-
var jsTemplate;
147-
for (i in settings.jsTemplates) {
148-
jsTemplate = settings.jsTemplates[i]
149-
.replaceAll('{multiple_index}', data.currentIndex)
150-
.replaceAll('%7Bmultiple_index%7D', data.currentIndex);
151-
window.eval(jsTemplate);
148+
var jsTemplate;
149+
for (i in settings.jsTemplates) {
150+
jsTemplate = settings.jsTemplates[i]
151+
.replaceAll('{multiple_index}', data.currentIndex)
152+
.replaceAll('%7Bmultiple_index%7D', data.currentIndex);
153+
window.eval(jsTemplate);
154+
}
155+
$wrapper.data('multipleInput').currentIndex++;
156+
157+
var event = $.Event(events.afterAddRow);
158+
$wrapper.trigger(event);
159+
};
160+
161+
var removeInput = function ($btn) {
162+
var $wrapper = $btn.closest('.multiple-input').first(),
163+
$toDelete = $btn.closest('.multiple-input-list__item'),
164+
count = $('.multiple-input-list__item').length,
165+
data = $wrapper.data('multipleInput'),
166+
settings = data.settings;
167+
168+
if (count > settings.min) {
169+
var event = $.Event(events.beforeDeleteRow);
170+
$wrapper.trigger(event, [$toDelete]);
171+
if (event.result === false) {
172+
return;
152173
}
153-
$wrapper.data('multipleInput').currentIndex++;
154174

155-
var event = $.Event(events.afterAddRow);
175+
$toDelete.find('input, select, textarea').each(function () {
176+
removeAttribute($(this));
177+
});
178+
179+
$toDelete.fadeOut(300, function () {
180+
$(this).remove();
181+
});
182+
183+
event = $.Event(events.afterDeleteRow);
156184
$wrapper.trigger(event);
157-
},
158-
159-
removeInput: function () {
160-
var $wrapper = $(this).closest('.multiple-input').first(),
161-
$toDelete = $(this).closest('.multiple-input-list__item'),
162-
count = $('.multiple-input-list__item').length,
163-
data = $wrapper.data('multipleInput'),
164-
settings = data.settings;
165-
166-
if (count > settings.min) {
167-
var event = $.Event(events.beforeDeleteRow);
168-
$wrapper.trigger(event, [$toDelete]);
169-
if (event.result === false) {
170-
return;
171-
}
185+
}
186+
};
172187

173-
$toDelete.find('input, select, textarea').each(function () {
174-
methods.removeAttribute.apply(this);
175-
});
176-
$toDelete.fadeOut(300, function () {
177-
$(this).remove();
178-
});
188+
var addAttribute = function (input) {
189+
var id = getInputId(input);
179190

180-
event = $.Event(events.afterDeleteRow);
181-
$wrapper.trigger(event);
182-
}
183-
},
191+
// skip if we could not get an ID of input
192+
if (id === null) {
193+
return;
194+
}
184195

185-
addAttribute: function () {
186-
var id = $(this).attr('id'),
187-
ele = $('#' + $(this).attr('id')),
188-
wrapper = ele.closest('.multiple-input').first(),
189-
form = ele.closest('form');
196+
var ele = $('#' + id),
197+
wrapper = ele.closest('.multiple-input').first(),
198+
form = ele.closest('form');
190199

191-
// do not add attribute which are not the part of widget
192-
if (wrapper.length == 0) {
193-
return;
194-
}
195200

196-
var data = wrapper.data('multipleInput');
197-
form.yiiActiveForm('add', $.extend({}, data.attributeDefaults, {
198-
'id': id,
199-
'input': '#' + id,
200-
'container': '.field-' + id
201-
}));
202-
},
201+
// do not add attribute which are not the part of widget
202+
if (wrapper.length == 0) {
203+
return;
204+
}
205+
206+
// check that input has been already added to the activeForm
207+
if (typeof form.yiiActiveForm('find', id) !== 'undefined') {
208+
return;
209+
}
203210

204-
removeAttribute: function () {
205-
var id = $(this).attr('id'),
206-
form = $('#' + $(this).attr('id')).closest('form');
211+
var data = wrapper.data('multipleInput');
212+
form.yiiActiveForm('add', $.extend({}, data.attributeDefaults, {
213+
'id': id,
214+
'input': '#' + id,
215+
'container': '.field-' + id
216+
}));
217+
};
207218

208-
if (form.length !== 0) {
209-
form.yiiActiveForm('remove', id);
210-
}
219+
var removeAttribute = function () {
220+
var id = getInputId($(this));
221+
222+
if (id === null) {
223+
return;
224+
}
225+
226+
var form = $('#' + id).closest('form');
227+
228+
if (form.length !== 0) {
229+
form.yiiActiveForm('remove', id);
230+
}
231+
};
232+
233+
var getInputId = function($input) {
234+
var id = $input.attr('id');
235+
236+
if (typeof id === 'undefined') {
237+
id = $input.data('id');
238+
}
239+
240+
if (typeof id === 'undefined') {
241+
return null;
211242
}
212243

244+
return id;
213245
};
214246

215247
String.prototype.replaceAll = function(search, replace){

src/assets/src/js/jquery.multipleInput.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/BaseColumn.php

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ public function init()
159159
*/
160160
public function isHiddenInput()
161161
{
162-
return $this->type == self::TYPE_HIDDEN_INPUT;
162+
return $this->type === self::TYPE_HIDDEN_INPUT;
163163
}
164164

165165

@@ -275,6 +275,8 @@ private function prepareItems($items)
275275
}
276276

277277
/**
278+
* Renders list box.
279+
*
278280
* @param $name
279281
* @param $value
280282
* @param $options
@@ -287,6 +289,8 @@ protected function renderListBox($name, $value, $options)
287289
}
288290

289291
/**
292+
* Renders hidden input.
293+
*
290294
* @param $name
291295
* @param $value
292296
* @param $options
@@ -298,6 +302,8 @@ protected function renderHiddenInput($name, $value, $options)
298302
}
299303

300304
/**
305+
* Renders radio button.
306+
*
301307
* @param $name
302308
* @param $value
303309
* @param $options
@@ -316,6 +322,8 @@ protected function renderRadio($name, $value, $options)
316322
}
317323

318324
/**
325+
* Renders radio button list.
326+
*
319327
* @param $name
320328
* @param $value
321329
* @param $options
@@ -326,14 +334,21 @@ protected function renderRadioList($name, $value, $options)
326334
if (!array_key_exists('unselect', $options)) {
327335
$options['unselect'] = '';
328336
}
329-
$options['item'] = function ($index, $label, $name, $checked, $value) {
330-
return '<div class="radio">' . Html::radio($name, $checked, ['label' => $label, 'value' => $value]) . '</div>';
337+
$options['item'] = function ($index, $label, $name, $checked, $value) use ($options) {
338+
$content = Html::radio($name, $checked, [
339+
'label' => $label,
340+
'value' => $value,
341+
'data-id' => ArrayHelper::getValue($options, 'id')
342+
]);
343+
return Html::tag('div', $content, ['class' => 'radio']);
331344
};
332345
$input = Html::radioList($name, $value, $this->prepareItems($this->items), $options);
333346
return Html::tag('div', $input, ['class' => 'radio-list']);
334347
}
335348

336349
/**
350+
* Renders checkbox.
351+
*
337352
* @param $name
338353
* @param $value
339354
* @param $options
@@ -352,6 +367,8 @@ protected function renderCheckbox($name, $value, $options)
352367
}
353368

354369
/**
370+
* Renders checkbox list.
371+
*
355372
* @param $name
356373
* @param $value
357374
* @param $options
@@ -362,14 +379,21 @@ protected function renderCheckboxList($name, $value, $options)
362379
if (!array_key_exists('unselect', $options)) {
363380
$options['unselect'] = '';
364381
}
365-
$options['item'] = function ($index, $label, $name, $checked, $value) {
366-
return '<div class="checkbox">' . Html::checkbox($name, $checked, ['label' => $label, 'value' => $value]) . '</div>';
382+
$options['item'] = function ($index, $label, $name, $checked, $value) use ($options) {
383+
$content = Html::checkbox($name, $checked, [
384+
'label' => $label,
385+
'value' => $value,
386+
'data-id' => ArrayHelper::getValue($options, 'id')
387+
]);
388+
return Html::tag('div', $content, ['class' => 'checkbox']);
367389
};
368390
$input = Html::checkboxList($name, $value, $this->prepareItems($this->items), $options);
369391
return Html::tag('div', $input, ['class' => 'checkbox-list']);
370392
}
371393

372394
/**
395+
* Renders an input.
396+
*
373397
* @param $name
374398
* @param $value
375399
* @param $options
@@ -393,6 +417,15 @@ protected function renderDefault($name, $value, $options)
393417
return $input;
394418
}
395419

420+
/**
421+
* Renders a widget.
422+
*
423+
* @param $type
424+
* @param $name
425+
* @param $value
426+
* @param $options
427+
* @return mixed
428+
*/
396429
protected function renderWidget($type, $name, $value, $options)
397430
{
398431
$model = $this->getModel();
@@ -418,6 +451,8 @@ protected function renderWidget($type, $name, $value, $options)
418451

419452

420453
/**
454+
* Renders an error.
455+
*
421456
* @param string $error
422457
* @return string
423458
*/

0 commit comments

Comments
 (0)