kartik-v / yii2-widget-depdrop

Widget that enables setting up dependent dropdowns with nested dependencies (sub repo split from yii2-widgets).
Other
82 stars 39 forks source link

DepDrop in TabularForm with Select2 #83

Closed strtob closed 3 years ago

strtob commented 3 years ago

Prerequisites

Hi!

This extension is really a great help!

Unfortunately, I try to use DepDrop with TabularForm. As far as I've understood, I do need for every entry a new id to make a unique dependency between parent and child. I try the following solution, but it won't work and ends with the error: Invalid Configuration – yii\base\InvalidConfigException The 'pluginOptions["depends"]' property must be set and must be an array of dependent dropdown element identifiers.

Is it possible to use an anoy. function and if not, is there any workaround to use it with TabularForms?

Thank you for help and best regards, Toby

`'tbl_company_id' => [ 'label' => Yii::t('app', 'Company'), 'type' => TabularForm::INPUT_WIDGET, 'widgetClass' => \kartik\widgets\Select2::className(), 'options' => function($model, $key, $index, $widget) { $initCompany = empty($model['tbl_company_id']) ? '' : \app\models\Company::findOne($model['tbl_company_id'])->name; return [
'options' => [ 'id' => 'tbl_companyid-id' . $model['id'], ], 'initValueText' => $initCompany, 'pluginOptions' => [ 'allowClear' => true, 'minimumInputLength' => 3, 'language' => [ 'errorLoading' => new JsExpression("function () { return 'Waiting for results...'; }"), ], 'ajax' => [ 'url' => \yii\helpers\Url::to(['/company/list']), 'dataType' => 'json', 'data' => new JsExpression('function(params) { return {q:params.term}; }') ], 'escapeMarkup' => new JsExpression('function (markup) { return markup; }'), 'templateResult' => new JsExpression('function(person) { return person.text; }'), 'templateSelection' => new JsExpression('function (person) { return person.text; }'), ], ]; },
'columnOptions' => ['width' => '200px'] ], 'tbl_person_id' => [ 'label' => Yii::t('app_company', 'Person'), 'type' => TabularForm::INPUT_WIDGET,
'widgetClass' => DepDrop::className(),

          'options' => [    
            'type' => DepDrop::TYPE_SELECT2,

            'options' => [
                'placeholder' => 'Select ...',
            ],

            'select2Options' => [
                'pluginOptions' => [
                    'allowClear' => true,
                    'initValueText' => 'test',
                    ]
            ],

            'pluginOptions' => [
                'depends' => function($model, $key, $index, $widget) { return ['tbl_company_id' . $model['id']]; },                   

                'initialize' => empty($model['id']) ? false : true,
                'url' => Url::to(['/person/depdrop']),
                'loadingText' => 'Loading Persons...',
            ]
        ], 

        'columnOptions' => ['width' => '200px'],
    ],`
--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/94478256-depdrop-in-tabularform-with-select2?utm_campaign=plugin&utm_content=tracker%2F8183994&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F8183994&utm_medium=issues&utm_source=github).
strtob commented 3 years ago

I've tried also with a closure, without success :-(

`$tmp_id;

echo TabularForm::widget([ 'dataProvider' => $dataProvider, 'formName' => 'TransactionHasMember', 'checkboxColumn' => false, 'actionColumn' => false, 'attributeDefaults' => [ 'type' => TabularForm::INPUT_TEXT, ], 'attributes' => [ 'id' => ['type' => TabularForm::INPUT_HIDDEN, 'columnOptions' => ['hidden'=>true]], 'tbl_transaction_member_role_id' => [ 'label' => 'Member role', 'type' => TabularForm::INPUT_WIDGET, 'widgetClass' => \kartik\widgets\Select2::className(), 'options' => [ 'data' => \yii\helpers\ArrayHelper::map(\app\models\TransactionMemberRole::find()->orderBy('name')->asArray()->all(), 'id', 'name'), 'options' => ['placeholder' => Yii::t('app', 'Choose member role')], ], 'columnOptions' => ['width' => '200px'] ], 'tbl_company_id' => [ 'label' => Yii::t('app', 'Company'), 'type' => TabularForm::INPUT_WIDGET, 'widgetClass' => \kartik\widgets\Select2::className(), 'options' => function($model, $key, $index, $widget) use ($tmp_id){ $initCompany = empty($model['tbl_company_id']) ? '' : \app\models\Company::findOne($model['tbl_company_id'])->name; $tmp_id = $key; return [
'options' => [ 'id' => 'tbl_companyid-id' . $key, ], 'initValueText' => $initCompany, 'pluginOptions' => [ 'allowClear' => true, 'minimumInputLength' => 3, 'language' => [ 'errorLoading' => new JsExpression("function () { return 'Waiting for results...'; }"), ], 'ajax' => [ 'url' => \yii\helpers\Url::to(['/company/list']), 'dataType' => 'json', 'data' => new JsExpression('function(params) { return {q:params.term}; }') ], 'escapeMarkup' => new JsExpression('function (markup) { return markup; }'), 'templateResult' => new JsExpression('function(person) { return person.text; }'), 'templateSelection' => new JsExpression('function (person) { return person.text; }'), ], ]; },
'columnOptions' => ['width' => '200px'] ], 'tbl_person_id' => [ 'label' => Yii::t('app_company', 'Person'), 'type' => TabularForm::INPUT_WIDGET,
'widgetClass' => DepDrop::className(),
'options' => [
'type' => DepDrop::TYPE_SELECT2,
'options' => [ 'placeholder' => 'Select ...', ],
'select2Options' => [ 'pluginOptions' => [ 'allowClear' => true, 'initValueText' => 'test', ] ],
'pluginOptions' => [ 'depends' => function() use ($tmp_id){ return ['tbl_company_idid' . $tmp_id]; },
'initialize' => empty($model['id']) ? false : true, 'url' => Url::to(['/person/depdrop']), 'loadingText' => 'Loading Persons...', ] ],
'columnOptions' => ['width' => '200px'], ], ], 'gridSettings' => [ 'panel' => [ 'heading' => false, 'type' => GridView::TYPE_DEFAULT, 'before' => false, 'footer' => false, 'after' => Html::button('' . Yii::t('app', 'Add Member'), ['type' => 'button', 'class' => 'btn btn-success kv-batch-create', 'onClick' => 'addRowTransactionHasMember()']), ] ] ]);`

fredyns commented 3 years ago

this works for me.

echo TabularForm::widget([
    'dataProvider' => $dataProvider,
    'form' => $form,
    'attributes' => [
        'grade_id' => [
            'type' => TabularForm::INPUT_RAW,
            'value' => function ($model, $key, $index, $widget) use ($form) {
                /* @var $model ModelClass */
                /* @var $key int */
                /* @var $index int */
                /* @var $widget TabularForm */
                return $form
                    ->field($model, 'attribute_name')
                    ->label(false)
                    ->widget(DepDrop::class,
                        [
                            //'options' => [],
                            'data' => [],
                            'type' => DepDrop::TYPE_SELECT2,
                            'select2Options' => [
                                'pluginOptions' => [
                                    'multiple' => FALSE,
                                    'allowClear' => TRUE,
                                    'tags' => TRUE,
                                    'maximumInputLength' => 255,
                                ],
                            ],
                            'pluginOptions' => [
                                'initialize' => TRUE,
                                'placeholder' => 'select',
                                'depends' => [
                                    strtolower($model->formName()) . "-{$key}-category_id",
                                    strtolower($model->formName()) . "-{$key}-substance_id",
                                ],
                                'url' => Url::to([
                                    "/.../depdrop-options",
                                    'selected' => $model->attribute_name,
                                ]),
                                'loadingText' => 'loading lah...',
                                'readonly' => true,
                            ],
                        ]);
            },
        ],
        ...
    ],
]);
strtob commented 3 years ago

Thanks a lot!

I've tried with this:

'tbl_person_id' => [ 'type' => TabularForm::INPUT_RAW, 'value' => function ($model, $key, $index, $widget) use ($form) { / @var $model ModelClass / / @var $key int / / @var $index int / / @var $widget TabularForm / return $form ->field($model, 'tbl_person_id') ->label(false) ->widget(DepDrop::class, [ //'options' => [], 'data' => [], 'type' => DepDrop::TYPE_SELECT2, 'select2Options' => [ 'pluginOptions' => [ 'multiple' => FALSE, 'allowClear' => TRUE, 'tags' => TRUE, 'maximumInputLength' => 255, ], ], 'pluginOptions' => [ 'initialize' => TRUE, 'placeholder' => 'select', 'depends' => [ strtolower('TransactionHasMember') . "-{$key}-tbl_company_id",
], 'url' => Url::to([ '/person/depdrop', //'selected' => $model['attribute_name'], ]), 'loadingText' => 'loading...', 'readonly' => false, ], ]); }, ],

but I've got every time this error:

`Call to a member function isAttributeRequired() on array

  1. in C:\Users\Tobia\work\rebase\vendor\yiisoft\yii2\widgets\ActiveField.phpat line 929 920921922923924925926927928929930931932933934935936937938 /**

    • Adds aria attributes to the input options.
    • @param $options array input options
    • @since 2.0.11 */ protected function addAriaAttributes(&$options) { if ($this->addAriaAttributes) { if (!isset($options['aria-required']) && $this->model->isAttributeRequired($this->attribute)) { $options['aria-required'] = 'true'; } if (!isset($options['aria-invalid']) && $this->model->hasErrors($this->attribute)) { $options['aria-invalid'] = 'true'; } } }

    /**

  2. in C:\Users\Tobia\work\rebase\vendor\yiisoft\yii2\widgets\ActiveField.php at line 791– yii\widgets\ActiveField::addAriaAttributes()
  3. in C:\Users\Tobia\work\rebase\views\transaction_formTransactionHasMember.php at line 111– yii\widgets\ActiveField::widget() 105106107108109110111112113114115116117 return $form ->field($model, 'tbl_person_id') ->label(false) ->widget(DepDrop::class, [ //'options' => [], 'data' => [], 'type' => DepDrop::TYPE_SELECT2, 'select2Options' => [ 'pluginOptions' => [ 'multiple' => FALSE, 'allowClear' => TRUE, 'tags' => TRUE,
  4. `
strtob commented 3 years ago

This is a nice solution, but I use mootensai/yii2-enhanced-gii for my project. This convert the entry models to arrays :-/

strtob commented 3 years ago

About 1 year later, I've solved it.

Here is the code for these guys, how also use mootensai/yii2-enhanced-gii with tabular forms and want to implement depdrop, this is just an example.

Attribute (column) one:

'tbl_basis_asset_type_id' => [
            'label' => Yii::t('app', 'Asset Type'),
            'type' => TabularForm::INPUT_RAW,
            'widgetClass' => \kartik\widgets\Select2::className(),
            'value' => function($model, $key, $index, $widget) {    
                return \kartik\select2\Select2::widget([
                    'name' => 'FPProfileHasBasisAssetType['.$key.'][tbl_basis_asset_type_id]',
                    'value' => [isset($model['tbl_basis_asset_type_id']) ? $model['tbl_basis_asset_type_id'] : ''], // default value
                    'data' => \yii\helpers\ArrayHelper::map(\app\models\BasisAssetType::find()->orderBy('name')->asArray()->all(), 'id', 'name'),
                    'options' => [
                        'id' => 'fpprofilehasbasisassettype-'.$key.'-tbl_basis_asset_type_id',
                    ],
                ]);     
            },            
            'columnOptions' => ['width' => '200px']
        ],

the depdrop (two):

'tbl_basis_asset_sub_type_id' => [
            'label' => Yii::t('app', 'Asset Sub Type'),
            'type' => TabularForm::INPUT_RAW,
            'value' => function($model, $key, $index, $widget) {

                $default = [];

                if(isset($model['tbl_basis_asset_sub_type_id']))
                {
                    $default = \yii\helpers\ArrayHelper::map(
                            \app\models\BasisAssetSubType::find()
                                ->where(['id' => $model['tbl_basis_asset_sub_type_id']])
                                ->asArray()
                                ->all(),
                        'id', 'name');
                }                                    

                return DepDrop::widget([
                    'name' => 'FPProfileHasBasisAssetType['.$key.'][tbl_basis_asset_sub_type_id]',
                    'options' => ['id'=>'fpprofilehasbasisassettype-'.$key.'-tbl_basis_asset_sub_type_id'],
                    'data' => $default,
                    'pluginOptions' => [
                       'initialize' => isset($model['tbl_basis_asset_sub_type_id']) ? false : true,
                       'depends'  => ['fpprofilehasbasisassettype-'.$key.'-tbl_basis_asset_type_id'],
                       'placeholder' => 'select ...',
                       'url' => Url::to(['/fp-profile/basis-sub-type']),                      
                    ]
                ]);                               
            }, 

            'columnOptions' => ['width' => '200px']
        ],

You have also set-up the controller action according to kartiks guide.

Best Toby