Skip to content

Commit

Permalink
Fixed ajax validation of radio/checkbox lists
Browse files Browse the repository at this point in the history
  • Loading branch information
unclead committed Mar 8, 2016
1 parent d7d6586 commit 4206c37
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 80 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Yii2 multiple input change log
---------------------

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

1.2.10
------
Expand Down
180 changes: 106 additions & 74 deletions src/assets/src/js/jquery.multipleInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,12 @@

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

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

var intervalID = setInterval(function(){
Expand All @@ -109,10 +109,11 @@
attributeDefaults[key] = value;
}
});

$wrapper.data('multipleInput').attributeDefaults = attributeDefaults;

$wrapper.find('.multiple-input-list').find('input, select, textarea').each(function () {
methods.addAttribute.apply(this);
addAttribute($(this));
});
$wrapper.data('multipleInput').currentIndex = $wrapper.find('.multiple-input-list__item').length;
clearInterval(intervalID);
Expand All @@ -121,95 +122,126 @@
$wrapper.trigger(event);
}
}, 100);
},
}
};

addInput: function () {
var $wrapper = $(this).closest('.multiple-input').first(),
data = $wrapper.data('multipleInput'),
settings = data.settings,
template = settings.template,
inputList = $wrapper.find('.multiple-input-list').first(),
count = $wrapper.find('.multiple-input-list__item').length;
var addInput = function (btn) {
var $wrapper = $(btn).closest('.multiple-input').first(),
data = $wrapper.data('multipleInput'),
settings = data.settings,
template = settings.template,
inputList = $wrapper.find('.multiple-input-list').first(),
count = $wrapper.find('.multiple-input-list__item').length;

if (settings.limit != null && count >= settings.limit) {
return;
}
if (settings.limit != null && count >= settings.limit) {
return;
}

template = template.replaceAll('{multiple_index}', data.currentIndex);
template = template.replaceAll('{multiple_index}', data.currentIndex);

$(template).hide().appendTo(inputList).fadeIn(300);
$(template).hide().appendTo(inputList).fadeIn(300);

$(template).find('input, select, textarea').each(function () {
methods.addAttribute.apply(this);
});
$(template).find('input, select, textarea').each(function () {
addAttribute($(this));
});

var jsTemplate;
for (i in settings.jsTemplates) {
jsTemplate = settings.jsTemplates[i]
.replaceAll('{multiple_index}', data.currentIndex)
.replaceAll('%7Bmultiple_index%7D', data.currentIndex);
window.eval(jsTemplate);
var jsTemplate;
for (i in settings.jsTemplates) {
jsTemplate = settings.jsTemplates[i]
.replaceAll('{multiple_index}', data.currentIndex)
.replaceAll('%7Bmultiple_index%7D', data.currentIndex);
window.eval(jsTemplate);
}
$wrapper.data('multipleInput').currentIndex++;

var event = $.Event(events.afterAddRow);
$wrapper.trigger(event);
};

var removeInput = function ($btn) {
var $wrapper = $btn.closest('.multiple-input').first(),
$toDelete = $btn.closest('.multiple-input-list__item'),
count = $('.multiple-input-list__item').length,
data = $wrapper.data('multipleInput'),
settings = data.settings;

if (count > settings.min) {
var event = $.Event(events.beforeDeleteRow);
$wrapper.trigger(event, [$toDelete]);
if (event.result === false) {
return;
}
$wrapper.data('multipleInput').currentIndex++;

var event = $.Event(events.afterAddRow);
$toDelete.find('input, select, textarea').each(function () {
removeAttribute($(this));
});

$toDelete.fadeOut(300, function () {
$(this).remove();
});

event = $.Event(events.afterDeleteRow);
$wrapper.trigger(event);
},

removeInput: function () {
var $wrapper = $(this).closest('.multiple-input').first(),
$toDelete = $(this).closest('.multiple-input-list__item'),
count = $('.multiple-input-list__item').length,
data = $wrapper.data('multipleInput'),
settings = data.settings;

if (count > settings.min) {
var event = $.Event(events.beforeDeleteRow);
$wrapper.trigger(event, [$toDelete]);
if (event.result === false) {
return;
}
}
};

$toDelete.find('input, select, textarea').each(function () {
methods.removeAttribute.apply(this);
});
$toDelete.fadeOut(300, function () {
$(this).remove();
});
var addAttribute = function (input) {
var id = getInputId(input);

event = $.Event(events.afterDeleteRow);
$wrapper.trigger(event);
}
},
// skip if we could not get an ID of input
if (id === null) {
return;
}

addAttribute: function () {
var id = $(this).attr('id'),
ele = $('#' + $(this).attr('id')),
wrapper = ele.closest('.multiple-input').first(),
form = ele.closest('form');
var ele = $('#' + id),
wrapper = ele.closest('.multiple-input').first(),
form = ele.closest('form');

// do not add attribute which are not the part of widget
if (wrapper.length == 0) {
return;
}

var data = wrapper.data('multipleInput');
form.yiiActiveForm('add', $.extend({}, data.attributeDefaults, {
'id': id,
'input': '#' + id,
'container': '.field-' + id
}));
},
// do not add attribute which are not the part of widget
if (wrapper.length == 0) {
return;
}

// check that input has been already added to the activeForm
if (typeof form.yiiActiveForm('find', id) !== 'undefined') {
return;
}

removeAttribute: function () {
var id = $(this).attr('id'),
form = $('#' + $(this).attr('id')).closest('form');
var data = wrapper.data('multipleInput');
form.yiiActiveForm('add', $.extend({}, data.attributeDefaults, {
'id': id,
'input': '#' + id,
'container': '.field-' + id
}));
};

if (form.length !== 0) {
form.yiiActiveForm('remove', id);
}
var removeAttribute = function () {
var id = getInputId($(this));

if (id === null) {
return;
}

var form = $('#' + id).closest('form');

if (form.length !== 0) {
form.yiiActiveForm('remove', id);
}
};

var getInputId = function($input) {
var id = $input.attr('id');

if (typeof id === 'undefined') {
id = $input.data('id');
}

if (typeof id === 'undefined') {
return null;
}

return id;
};

String.prototype.replaceAll = function(search, replace){
Expand Down
2 changes: 1 addition & 1 deletion src/assets/src/js/jquery.multipleInput.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 40 additions & 5 deletions src/components/BaseColumn.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public function init()
*/
public function isHiddenInput()
{
return $this->type == self::TYPE_HIDDEN_INPUT;
return $this->type === self::TYPE_HIDDEN_INPUT;
}


Expand Down Expand Up @@ -275,6 +275,8 @@ private function prepareItems($items)
}

/**
* Renders list box.
*
* @param $name
* @param $value
* @param $options
Expand All @@ -287,6 +289,8 @@ protected function renderListBox($name, $value, $options)
}

/**
* Renders hidden input.
*
* @param $name
* @param $value
* @param $options
Expand All @@ -298,6 +302,8 @@ protected function renderHiddenInput($name, $value, $options)
}

/**
* Renders radio button.
*
* @param $name
* @param $value
* @param $options
Expand All @@ -316,6 +322,8 @@ protected function renderRadio($name, $value, $options)
}

/**
* Renders radio button list.
*
* @param $name
* @param $value
* @param $options
Expand All @@ -326,14 +334,21 @@ protected function renderRadioList($name, $value, $options)
if (!array_key_exists('unselect', $options)) {
$options['unselect'] = '';
}
$options['item'] = function ($index, $label, $name, $checked, $value) {
return '<div class="radio">' . Html::radio($name, $checked, ['label' => $label, 'value' => $value]) . '</div>';
$options['item'] = function ($index, $label, $name, $checked, $value) use ($options) {
$content = Html::radio($name, $checked, [
'label' => $label,
'value' => $value,
'data-id' => ArrayHelper::getValue($options, 'id')
]);
return Html::tag('div', $content, ['class' => 'radio']);
};
$input = Html::radioList($name, $value, $this->prepareItems($this->items), $options);
return Html::tag('div', $input, ['class' => 'radio-list']);
}

/**
* Renders checkbox.
*
* @param $name
* @param $value
* @param $options
Expand All @@ -352,6 +367,8 @@ protected function renderCheckbox($name, $value, $options)
}

/**
* Renders checkbox list.
*
* @param $name
* @param $value
* @param $options
Expand All @@ -362,14 +379,21 @@ protected function renderCheckboxList($name, $value, $options)
if (!array_key_exists('unselect', $options)) {
$options['unselect'] = '';
}
$options['item'] = function ($index, $label, $name, $checked, $value) {
return '<div class="checkbox">' . Html::checkbox($name, $checked, ['label' => $label, 'value' => $value]) . '</div>';
$options['item'] = function ($index, $label, $name, $checked, $value) use ($options) {
$content = Html::checkbox($name, $checked, [
'label' => $label,
'value' => $value,
'data-id' => ArrayHelper::getValue($options, 'id')
]);
return Html::tag('div', $content, ['class' => 'checkbox']);
};
$input = Html::checkboxList($name, $value, $this->prepareItems($this->items), $options);
return Html::tag('div', $input, ['class' => 'checkbox-list']);
}

/**
* Renders an input.
*
* @param $name
* @param $value
* @param $options
Expand All @@ -393,6 +417,15 @@ protected function renderDefault($name, $value, $options)
return $input;
}

/**
* Renders a widget.
*
* @param $type
* @param $name
* @param $value
* @param $options
* @return mixed
*/
protected function renderWidget($type, $name, $value, $options)
{
$model = $this->getModel();
Expand All @@ -418,6 +451,8 @@ protected function renderWidget($type, $name, $value, $options)


/**
* Renders an error.
*
* @param string $error
* @return string
*/
Expand Down

0 comments on commit 4206c37

Please sign in to comment.