#Yii2 Multiple input widget. Yii2 widget for handle multiple inputs for an attribute of model
##Latest release The latest version of the extension is v1.2.19. Follow the instruction for upgrading from previous versions
Contents:
- Installation
- Configuration
- Usage
- Tips and tricks
- How to customize buttons
- Work with empty list
- Guess column title
- Ajax loading of a widget
- Use of a widget's placeholder
- Custom index of the row
- Javascript Events
- Renderers
##Installation The preferred way to install this extension is through composer.
Either run
php composer.phar require unclead/yii2-multiple-input "~1.0"
or add
"unclead/yii2-multiple-input": "~1.0"
to the require section of your composer.json
file.
Widget support the following options that are additionally recognized over and above the configuration options in the InputWidget.
limit integer: rows limit. If not set will defaul to unlimited
min integer: minimum number of rows. Set to 0
if you need the empty list in case you don't have any data
attributeOptions array: client-side attribute options, e.g. enableAjaxValidation. You may use this property in case when you use widget without a model, since in this case widget is not able to detect client-side options automatically
addButtonPosition integer: the position of add
button. This can be MultipleInput::POS_HEADER or MultipleInput::POS_ROW.
addButtonOptions array: the HTML options for add
button. Can contains class
and label
keys
removeButtonOptions array: the HTML options for add
button. Can contains class
and label
keys
data array: array of values in case you use widget without model
models array: the list of models. Required in case you use TabularInput
widget
allowEmptyList boolean: whether to allow the empty list
columnClass string: the name of column class. You can specify your own class to extend base functionality.
Defaults to unclead\widgets\MultipleInputColumn
for MultipleInput
and unclead\widgets\TabularColumn
for TabularInput
.
columns array: the row columns configuration where you can set the properties which is described below
rowOptions array|\Closure: the HTML attributes for the table body rows. This can be either an array specifying the common HTML attributes for all body rows, or an anonymous function that returns an array of the HTML attributes. It should have the following signature:
function ($model, $index, $context)
$model
: the current data model being rendered$index
: the zero-based index of the data model in the model array$context
: the widget object
name string: input name. Required options
type string: type of the input. If not set will default to textInput
. Read more about the types described below
title string: the column title
value Closure: you can set it to an anonymous function with the following signature:
function($data) {}
defaultValue string: default value of input
items array|Closure: the items for input with type dropDownList, listBox, checkboxList, radioList or anonymous function which return array of items and has the following signature:
function($data) {}
options array|Closure: the HTML attributes for the input, you can set it as array or an anonymous function with the following signature:
function($data) {}
headerOptions array: the HTML attributes for the header cell
enableError boolean: whether to render inline error for the input. Default to false
errorOptions array: the HTMl attributes for the error tag
Each column in a row can has their own type. Widget supports:
- all yii2 html input types:
textInput
dropDownList
radioList
textarea
- For more detail look at Html helper class
- input widget (widget that extends from
InputWidget
class). For example,yii\widgets\MaskedInput
static
to output a static HTML content
For using widget as column input you may use the following code:
[
'name' => 'phone',
'title' => 'Phone number',
'type' => \yii\widgets\MaskedInput::className(),
'options' => [
'class' => 'input-phone',
'mask' => '999-999-99-99'
]
]
##Usage
For example you want to have an ability of entering several emails of user on profile page. In this case you can use yii2-multiple-input widget like in the following code
use unclead\widgets\MultipleInput;
...
<?php
echo $form->field($model, 'emails')->widget(MultipleInput::className(), [
'limit' => 6,
'allowEmptyList' => false,
'enableGuessTitle' => true,
'min' => 2, // should be at least 2 rows
'addButtonPosition' => MultipleInput::POS_HEADER // show add button in the header
])
->label(false);
?>
You can find more detail about this use case here
For example you keep some data in json format in attribute of model. Imagine that it is an abstract user schedule with keys: user_id, day, priority
On the edit page you want to be able to manage this schedule and you can you yii2-multiple-input widget like in the following code
use unclead\widgets\MultipleInput;
...
<?= $form->field($model, 'schedule')->widget(MultipleInput::className(), [
'limit' => 4,
'columns' => [
[
'name' => 'user_id',
'type' => 'dropDownList',
'title' => 'User',
'defaultValue' => 1,
'items' => [
1 => 'User 1',
2 => 'User 2'
]
],
[
'name' => 'day',
'type' => \kartik\date\DatePicker::className(),
'title' => 'Day',
'value' => function($data) {
return $data['day'];
},
'items' => [
'0' => 'Saturday',
'1' => 'Monday'
],
'options' => [
'pluginOptions' => [
'format' => 'dd.mm.yyyy',
'todayHighlight' => true
]
],
'headerOptions' => [
'style' => 'width: 250px;',
'class' => 'day-css-class'
]
],
[
'name' => 'priority',
'enableError' => true,
'title' => 'Priority',
'options' => [
'class' => 'input-priority'
]
],
[
'name' => 'comment',
'type' => 'static',
'value' => function($data) {
return Html::tag('span', 'static content', ['class' => 'label label-info']);
},
'headerOptions' => [
'style' => 'width: 70px;',
]
]
]
]);
?>
You can find more detail about this use case here
For example you want to manage some models via tabular input. In this case you can use TabularInput
widget which is based on MultipleInput
widget.
Use the following code for this purpose:
<?= TabularInput::widget([
'models' => $models,
'attributeOptions' => [
'enableAjaxValidation' => true,
'enableClientValidation' => false,
'validateOnChange' => false,
'validateOnSubmit' => true,
'validateOnBlur' => false,
],
'columns' => [
[
'name' => 'title',
'title' => 'Title',
'type' => TabularInputColumn::TYPE_TEXT_INPUT,
],
[
'name' => 'description',
'title' => 'Description',
],
[
'name' => 'file',
'title' => 'File',
'type' => \vova07\fileapi\Widget::className(),
'options' => [
'settings' => [
'url' => ['site/fileapi-upload']
]
]
],
[
'name' => 'date',
'type' => \kartik\date\DatePicker::className(),
'title' => 'Day',
'options' => [
'pluginOptions' => [
'format' => 'dd.mm.yyyy',
'todayHighlight' => true
]
],
'headerOptions' => [
'style' => 'width: 250px;',
'class' => 'day-css-class'
]
],
],
]) ?>
You can find more detail about this use case here
Also you can find source code of examples here
You can customize add
and remove
buttons via addButtonOptions
and removeButtonOptions
. Here is the simple example
how you can use those options:
echo $form->field($model, 'emails')->widget(MultipleInput::className(), [
'limit' => 5,
'addButtonOptions' => [
'class' => 'btn btn-success',
'label' => 'add' // also you can use html code
],
'removeButtonOptions' => [
'label' => 'remove'
]
])
->label(false);
In some cases you need to have the ability to delete all rows in the list. For this purpose you can use option allowEmptyList
like in the example below:
echo $form->field($model, 'emails')->widget(MultipleInput::className(), [
'limit' => 5,
'allowEmptyList' => true
])
->label(false);
Also you can set 0
in min
option if you don't need first blank row when data is empty.
Sometimes you can use the widget without defining columns but you want to have the column header of the table.
In this case you can use enableGuessTitle
option like in the example below:
echo $form->field($model, 'emails')->widget(MultipleInput::className(), [
'limit' => 5,
'allowEmptyList' => true,
'enableGuessTitle' => true
])
->label(false);
Assume you want to load a widget via ajax and then show it inside modal window. In this case you MUST:
- Ensure that you specified ID of widget otherwise the widget will get random ID and it can be the same as id of others elements on the page.
- Ensure that you use the widget inside ActiveForm because it works incorrectly in this case.
You can fina an example of usage in a discussion of issue
You can use a placeholder {multiple index}
in a widget configuration, e.g. for implementation of dependent drop down lists.
<?= $form->field($model, 'field')->widget(MultipleInput::className(), [
'allowEmptyList' => false,
'rowOptions' => [
'id' => 'row{multiple_index}',
],
'columns' => [
[
'name' => 'category',
'type' => 'dropDownList',
'title' => 'Category',
'defaultValue' => '1',
'items' => [
'1' => 'Test 1',
'2' => 'Test 2',
'3' => 'Test 3',
'4' => 'Test 4',
],
'options' => [
'onchange' => <<< JS
$.post("list?id=" + $(this).val(), function(data){
console.log(data);
$("select#subcat-{multiple_index}").html(data);
});
JS
],
],
[
'name' => 'subcategory',
'type' => 'dropDownList',
'title' => 'Subcategory',
'items' => [],
'options'=> [
'id' => 'subcat-{multiple_index}'
],
],
]
]);
?>
Assume that you want to set specific index for each row. In this case you can pass the data
attribute as associative array
as in the example below:
<?= $form->field($model, 'field')->widget(MultipleInput::className(), [
'allowEmptyList' => false,
'data' => [
3 => [
'day' => '27.02.2015',
'user_id' => 31,
'priority' => 1,
'enable' => 1
],
'some-key' => [
'day' => '27.02.2015',
'user_id' => 33,
'priority' => 2,
'enable' => 0
],
]
...
This widget has following events:
afterInit
: triggered after initializationafterAddRow
: triggered after new row insertionbeforeDeleteRow
: triggered before the row removalafterDeleteRow
: triggered after the row removal
Example:
jQuery('#multiple-input').on('afterInit', function(){
console.log('calls on after initialization event');
}).on('beforeAddRow', function(e) {
console.log('calls on before add row event');
}).on('afterAddRow', function(e) {
console.log('calls on after add row event');
}).on('beforeDeleteRow', function(e, row){
// row - HTML container of the current row for removal.
// For TableRenderer it is tr.multiple-input-list__item
console.log('calls on before remove row event.');
return confirm('Are you sure you want to delete row?')
}).on('afterDeleteRow', function(){
console.log('calls on after remove row event');
});
Dynamically operations in widget:
add
: adding new row, param object: object with values for inputs, can be filled with tags for dynamically added options for select (for ajax select).remove
: remove row, param integer: row number for removing, if not specified then removes last row.clear
: remove all rows
Examples:
$('#multiple-input').multipleInput('add', {first: 10, second: '<option value="2" selected="selected">second</option>'});
$('#multiple-input').multipleInput('remove', 2);
$('#multiple-input').multipleInput('clear');
##Renderers
Section is under development
Currently widget supports only TableRenderer
which renders content in table format.
##License
yii2-multiple-input is released under the BSD 3-Clause License. See the bundled LICENSE.md for details.