Hello,
I’m new in the Forum, but not in Yii2 site. We’re working on a backend application, with a product form that is creating/updating some different models data related to the product. The product can be categorized using its related model Category, and depending of this Category, the product can have or not some attributes and values for these attributes. These attributes and Values are also defined in another database models Attribute and Value.
In the form, first the Category must be selected in a dropdown and later, the Attributes should be selected depending of the Category of the product belong to.
We created this ProductController, for example for action Update:
public function actionUpdate($id)
{
if (Yii::$app->request->post('_asnew') == '1') {
$model = new Product();
}else{
$model = $this->findModel($id);
$i = count($model->images)+1;
}
if ($model->loadAll(Yii::$app->request->post(), ['reviews', 'questions'])) {
$model->imagenes = UploadedFile::getInstances($model, 'imagenes');
if ($model->saveAll(['reviews', 'questions'])) {
foreach ($model->imagenes as $imagen) {
$path = $model->imageFolder.$imagen->extension;
$image = new Image();
$image->product_id = $model->id;
$image->path = $path;
$image->order = $i;
if ($image->save()) {
$imagen->saveAs("images/".$path);
}
$i++;
}
return $this->redirect(['tamano', 'id' => $model->id]);
} else {
Yii::$app->getSession()->setFlash('error', 'Error updating the Product');
}
}
return $this->render('update', ['model' => $model]);
}
In the form, we have the first Category field as usual:
<?= Html::activeLabel($model, 'category_id', ['label'=>'Categoría', 'class'=>'col-sm-1 control-label']) ?>
<div class="col-sm-4">
<?= $form->field($model, 'category_id', ['showLabels'=>false])->widget(\kartik\widgets\Select2::classname(), [
'data' => $model->hierarchy,
'options' => ['placeholder' => 'Select Category'],
'pluginOptions' => [
'allowClear' => true
],
]); ?>
</div>
And in the same form, later we have the Attributes section in a Tab (from Kartik TabsX Widget), defined as this:
[
'label' => '<i class="glyphicon glyphicon-list-alt"></i> '.Html::encode('Attributes'),
'content' => $this->render('_formProdAtrVal', [
'row' => \yii\helpers\ArrayHelper::toArray($model->prodAtrVals)
]),
],
This form is rendering this other view file with a Tabular form, because the Attributes of a Product can be 0 to N, depending on the Product category. So with this form you can Add attributes dinamically:
<div class="form-group" id="add-prod-atr-val">
<?php
use kartik\grid\GridView;
use kartik\builder\TabularForm;
use yii\data\ArrayDataProvider;
use yii\helpers\Html;
use yii\widgets\Pjax;
$dataProvider = new ArrayDataProvider([
'allModels' => $row,
'pagination' => [
'pageSize' => -1
]
]);
echo TabularForm::widget([
'dataProvider' => $dataProvider,
'formName' => 'ProdAtrVal',
'checkboxColumn' => false,
'actionColumn' => false,
'attributeDefaults' => [
'type' => TabularForm::INPUT_TEXT,
],
'attributes' => [
"id" => ['type' => TabularForm::INPUT_HIDDEN, 'columnOptions' => ['hidden'=>true]],
'atributo_id' => [
'label' => 'Atributo',
'type' => TabularForm::INPUT_WIDGET,
'widgetClass' => \kartik\widgets\Select2::className(),
'options' => [
'data' => \yii\helpers\ArrayHelper::map(\backend\models\Atributo::find()->orderBy('id')->asArray()->all(), 'id', 'name'),
'options' => ['placeholder' => 'Escoge'],
],
'columnOptions' => ['width' => '200px']
],
'valor_id' => [
'label' => 'Valor',
'type' => TabularForm::INPUT_WIDGET,
'widgetClass' => \kartik\widgets\Select2::className(),
'options' => [
'data' => \yii\helpers\ArrayHelper::map(\backend\models\Valor::find()->orderBy('valor')->asArray()->all(), 'id', 'valor'),
'options' => ['placeholder' => 'Escoge'],
],
'columnOptions' => ['width' => '200px']
],
'del' => [
'type' => 'raw',
'label' => '',
'value' => function($model, $key) {
return
Html::hiddenInput('Children[' . $key . '][id]', (!empty($model['id'])) ? $model['id'] : "") .
Html::a('<i class="glyphicon glyphicon-trash"></i>', '#', ['title' => 'Delete', 'onClick' => 'delRowProdAtrVal(' . $key . '); return false;', 'id' => 'prod-atr-val-del-btn']);
},
],
],
'gridSettings' => [
'panel' => [
'heading' => false,
'type' => GridView::TYPE_DEFAULT,
'before' => false,
'footer' => false,
'after' => Html::button('<i class="glyphicon glyphicon-plus"></i>' . 'Add Attribute', ['type' => 'button', 'class' => 'btn btn-success kv-batch-create', 'onClick' => 'addRowProdAtrVal()']),
]
]
]);
echo " </div>\n\n";
?>
When you click on Add attribute button, an Ajax call is created to this controller action:
public function actionAddProdAtrVal()
{
if (Yii::$app->request->isAjax) {
$row = Yii::$app->request->post('ProdAtrVal');
if((Yii::$app->request->post('isNewRecord') && Yii::$app->request->post('_action') == 'load' && empty($row)) || Yii::$app->request->post('_action') == 'add')
$row[] = [];
return $this->renderAjax('_formProdAtrVal', ['row' => $row]);
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
With this configuration I can add multiple attributes to the Product, but the problem is that the dropdown with attribute list and values are not depending on the Product category. I don’t know how to dinamically restrict the attribute dropdown list for the attrubtes of the product category. It can be done with something like:
'data' => \yii\helpers\ArrayHelper::map(\backend\models\Atributo::find()->where(['category_id' => $category])->orderBy('id')->asArray()->all(), 'id', 'name'),
An use that $category variable to dinamically select the attributes for the product category. We test some solutions using ajax to dinamically update the Attributes tab when the Category field is updated (when creating a Product), but no results.
Have you any better aproximation to solve the problem we have?
I attach all completed involved files if you need them.
Thank you!