wbraganca / yii2-dynamicform

It is widget to yii2 framework to clone form elements in a nested manner, maintaining accessibility.
Other
436 stars 438 forks source link

Can Create but can't update, it removes all order items of my database #66

Open fsc7 opened 9 years ago

fsc7 commented 9 years ago

Hello,

I follow the tutorial and now I am able to create an order and it's items and save it to the database, but for some reason the update is not working. It seems that it deletes all my order items and goes to the view page.

_form.php

       <?php DynamicFormWidget::begin([
          'widgetContainer' => 'dynamicform_wrapper', // required: only alphanumeric characters plus "_" [A-Za-z0-9_]
          'widgetBody' => '.container-items', // required: css class selector
          'widgetItem' => '.item', // required: css class
          'limit' => 200, // the maximum times, an element can be cloned (default 999)
          'min' => 0, // 0 or 1 (default 1)
          'insertButton' => '.add-item', // css class
          'deleteButton' => '.remove-item', // css class
          'model' => $modelOrderItems[0],
          'formId' => 'dynamic-form',
          'formFields' => [
              'product_id',
              'quantity',
              'price',
              'status_id',
          ],
        ]); ?>

      <div class="panel panel-default">
        <div class="panel-heading">
          <h4><i class="glyphicon glyphicon-envelope"></i>Order Items
            <button type="button" class="add-item btn btn-success btn-sm pull-right"><i class="glyphicon glyphicon-plus"></i> Add</button>
          </h4>
        </div>
      <div class="panel-body">
        <div class="container-items"><!-- widgetContainer -->
        <?php foreach ($modelOrderItems as $orderItem => $modelOrderItem): ?>
            <div class="item panel panel-default"><!-- widgetBody -->
                <div class="panel-heading">
                    <h3 class="panel-title pull-left">Order items</h3>
                    <div class="pull-right">
                        <button type="button" class="add-item btn btn-success btn-xs"><i class="glyphicon glyphicon-plus"></i></button>
                        <button type="button" class="remove-item btn btn-danger btn-xs"><i class="glyphicon glyphicon-minus"></i></button>
                    </div>
                    <div class="clearfix"></div>
                </div>
                <div class="panel-body">
                    <?php
                        // necessary for update action.
                        if (! $modelOrderItem->isNewRecord) {
                            echo Html::activeHiddenInput($modelOrderItem, "[{$orderItem}]id");
                        }
                    ?>
                    <div class="row">
                      <?= Html::activeLabel($modelOrderItem, 'product_id', ['label'=>'Product', 'class'=>'col-sm-1 control-label']) ?>
                      <div class="col-sm-2">
                        <?= $form->field($modelOrderItem, "[{$orderItem}]product_id")->dropDownList(ArrayHelper::map(Product::find()->orderBy(['name'=>SORT_ASC])->all(), 'id', 'name'),['prompt'=>'Select Product']); ?>
                      </div>
                      <?= Html::activeLabel($modelOrderItem, 'quantity', ['label'=>'Quantity', 'class'=>'col-sm-1 control-label']) ?>
                      <div class="col-sm-2">
                        <?= $form->field($modelOrderItem, "[{$orderItem}]quantity")->textInput(['maxlength' => true]) ?>
                      </div>
                      <?= Html::activeLabel($modelOrderItem, 'price', ['label'=>'Price', 'class'=>'col-sm-1 control-label']) ?>
                      <div class="col-sm-2">
                        <?= $form->field($modelOrderItem, "[{$orderItem}]price")->textInput(['maxlength' => true]) ?>
                      </div>
                      <?= Html::activeLabel($modelOrderItem, 'status_id', ['label'=>'Status', 'class'=>'col-sm-1 control-label']) ?>
                      <div class="col-sm-2">
                        <?= $form->field($modelOrderItem, "[{$orderItem}]status_id")->dropDownList(ArrayHelper::map(Status::find()->orderBy(['name'=>SORT_ASC])->all(), 'id', 'name'),['prompt'=>'Select Product']); ?>
                      </div>
                    </div><!-- .row -->
                </div>
              </div>
            <?php endforeach; ?>
            </div>
          </div>
        </div>
        <?php DynamicFormWidget::end(); ?>

      <div class="form-group">
        <div class="col-sm-12">
          <hr>
          <?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
        </div>
      </div>
    </div>
    <?php ActiveForm::end(); ?>

Throw this error on line 78

Undefined variable: modelOrderItems 'model' => $modelOrderItems[0],

This is my controller

<?php

namespace app\controllers;

use Yii;
use app\models\WholesalerOrder;
use app\models\WholesalerOrderItem;
use app\models\WholesalerOrderSearch;
use app\models\base\Model;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\helpers\ArrayHelper;

/**
 * WholesalerOrderController implements the CRUD actions for WholesalerOrder model.
 */
class WholesalerOrderController extends Controller
{
    public function behaviors()
    {
        return [
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'delete' => ['post'],
                ],
            ],
        ];
    }

    /**
     * Lists all WholesalerOrder models.
     * @return mixed
     */
    public function actionIndex()
    {
        $searchModel = new WholesalerOrderSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }

    /**
     * Displays a single WholesalerOrder model.
     * @param integer $id
     * @return mixed
     */
    public function actionView($id)
    {
        return $this->render('view', [
            'model' => $this->findModel($id),
        ]);
    }

    /**
     * Creates a new WholesalerOrder model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     * @return mixed
     */
    public function actionCreate()
    {
        $model = new WholesalerOrder();
        $modelOrderItems = [new WholesalerOrderItem];

        if ($model->load(Yii::$app->request->post()) && $model->save()) {

          $modelOrderItems = Model::createMultiple(WholesalerOrderItem::classname());
          Model::loadMultiple($modelOrderItems, Yii::$app->request->post());

          // validate all models
          $valid = $model->validate();
          $valid = Model::validateMultiple($modelOrderItems) && $valid;

          if ($valid) {
              $transaction = \Yii::$app->db->beginTransaction();
              try {
                  if ($flag = $model->save(false)) {
                      foreach ($modelOrderItems as $modelOrderItem) {
                          $modelOrderItem->order_id = $model->id;
                          if (! ($flag = $modelOrderItem->save(false))) {
                              $transaction->rollBack();
                              break;
                          }
                      }
                  }
                  if ($flag) {
                      $transaction->commit();
                      return $this->redirect(['view', 'id' => $model->id]);
                  }
              } catch (Exception $e) {
                  $transaction->rollBack();
              }
          }
        } else {
            return $this->render('create', [
                'model' => $model,
                'modelOrderItems' => (empty($modelOrderItems)) ? [new WholesalerOrderItem] : $modelOrderItems
            ]);
        }
    }

    /**
     * Updates an existing WholesalerOrder model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param integer $id
     * @return mixed
     */
    public function actionUpdate($id)
    {
        $model = $this->findModel($id);
        $modelOrderItems = $model->wholesalerOrderItems;

        $oldIDs = ArrayHelper::map($modelOrderItems, 'id', 'id');
        print_r($oldIDs);
        $modelOrderItems = Model::createMultiple(WholesalerOrderItem::classname(), $modelOrderItems);
        Model::loadMultiple($modelOrderItems, Yii::$app->request->post());
        $deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelOrderItems, 'id', 'id')));

        // ajax validation
        if (Yii::$app->request->isAjax) {
            Yii::$app->response->format = Response::FORMAT_JSON;
            return ArrayHelper::merge(
                ActiveForm::validateMultiple($modelOrderItems),
                ActiveForm::validate($model)
            );
        }

        // validate all models
        $valid = $model->validate();
        $valid = Model::validateMultiple($modelOrderItems) && $valid;

        if ($valid) {
            $transaction = \Yii::$app->db->beginTransaction();
            try {
                if ($flag = $model->save(false)) {
                    if (! empty($deletedIDs)) {
                        WholesalerOrderItem::deleteAll(['id' => $deletedIDs]);
                    }
                    foreach ($modelOrderItems as $modelOrderItem) {
                        $modelOrderItem->order_id = $model->id;
                        if (! ($flag = $modelOrderItem->save(false))) {
                            $transaction->rollBack();
                            break;
                        }
                    }
                }
                if ($flag) {
                    $transaction->commit();
                    //return $this->redirect(['view', 'id' => $model->id]);
                }
            } catch (Exception $e) {
                $transaction->rollBack();
            }
        }
        return $this->render('update', [
            'model' => $model,
            '$modelOrderItems' => (empty($modelOrderItems)) ? [new WholesalerOrderItem] : $modelOrderItems
        ]);
    }

    /**
     * Deletes an existing WholesalerOrder model.
     * If deletion is successful, the browser will be redirected to the 'index' page.
     * @param integer $id
     * @return mixed
     */
    public function actionDelete($id)
    {
        $this->findModel($id)->delete();

        return $this->redirect(['index']);
    }

    /**
     * Finds the WholesalerOrder model based on its primary key value.
     * If the model is not found, a 404 HTTP exception will be thrown.
     * @param integer $id
     * @return WholesalerOrder the loaded model
     * @throws NotFoundHttpException if the model cannot be found
     */
    protected function findModel($id)
    {
        if (($model = WholesalerOrder::findOne($id)) !== null) {
            return $model;
        } else {
            throw new NotFoundHttpException('The requested page does not exist.');
        }
    }
}

Anyone can help me? Thanks in advance.

fsc7 commented 9 years ago

Thanks. i find my mistake. $ '$modelOrderItems' => (empty($modelOrderItems)) ? [new WholesalerOrderItem] : $modelOrderItems

xiandalisay commented 9 years ago

@fsc7 Have you loaded the update.php file? It seems in your actionUpdate that it renders the view file. Same in my case. I have also update problems.

xiandalisay commented 9 years ago

Here's my code. This is in the child member controller. I called the findModel of parent recognition

/* * Updates an existing Member model. * If update is successful, the browser will be redirected to the 'view' page. * @param integer $id * @return mixed / public function actionUpdate($id) { $rec = \frontend\models\Recognition::findOne($id); $models = $rec->members;

    $oldIDs = ArrayHelper::map($models, 'id', 'id');
    $models = Model::createMultiple(Member::classname(), $models);
        if(Model::loadMultiple($models, Yii::$app->request->post())) {
        $deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($models, 'id', 'id')));

        // ajax validation
        if (Yii::$app->request->isAjax) {
            Yii::$app->response->format = Response::FORMAT_JSON;
            return ArrayHelper::merge(
                ActiveForm::validateMultiple($models),
                ActiveForm::validate($rec)
            );
        }

        // validate all models
        $valid = $rec->validate();
        $valid = Model::validateMultiple($models) && $valid;

        if ($valid) {
            $transaction = \Yii::$app->db->beginTransaction();
            try {
                if ($flag = $rec->save(false)) {
                    if (! empty($deletedIDs)) {
                        Member::deleteAll(['id' => $deletedIDs]);
                    }
                    foreach ($models as $model) {
                        $model->rec_id = $rec->id;
                        if (! ($flag = $model->save(false))) {
                            $transaction->rollBack();
                            break;
                        }
                    }
                }
                if ($flag) {
                    $transaction->commit();
                    return $this->redirect(['view', 'id' => $rec->id]);
                }
            } catch (Exception $e) {
                $transaction->rollBack();
            }
        }
    }

    return $this->render('update', [
        'rec' => $rec,
        'models' => (empty($models)) ? [new Member] : $models,
        'id' => $id,
    ]);

} After rendering of the form.php, it's always create not update.

fsc7 commented 9 years ago

I don't know if I understood well your problem. In my case I had a class Orders and Order Items, so in OrderController I did the save. You said you are making it on the child? If so you just need a normal Controller which can be generated by Gii. Maybe I misundertood what you said, sorry.

But there is also something which is not writen anywhere, at least that I have seen. Your update view must be like this.

<div class="incoming-order-update">

    <h1><?= Html::encode($this->title) ?></h1>

    <?= $this->render('_form', [
        'model' => $model,
        'modelIncOrderItems'=>$modelIncOrderItems,
    ]) ?>

</div>

With your child being also passed to the controler.

Regards,

Felipe

xiandalisay commented 9 years ago

Yes, the child should be passed into the view. Else, it will cause error.

I am creating and updating in the child controller. This is to separate the forms (parent and child) for updating.

If I did it on the parentController, the first call should be $model = $this->findModel($id); Since I'm doing it in the child controller, I called the parent \frontend\models\Recognition::findOne($id); They have the same semantics.

In the first call of update. The values are not rendered. but I used var_dump to see if there are child instances. And there it is. So the values should be in the form.

capture

xiandalisay commented 9 years ago

I got it. Its my fault. Now, I don't recommend directly implementing on the childController and just taking the instance of the parentmodel to get the childmodel. Thanks for the reply.

fsc7 commented 9 years ago

Good. What was the problem so we can all learn?

xiandalisay commented 9 years ago

I was wrong. I hadn't really resolved the issue. But what I learned, that it does not work when youre implementing in the child controller. actionUpdate. For example,

$rec = \frontend\models\Recognition::findOne($id); $models = $rec->members; // This returns empty

@fsc7 Currently, I'm still on the same issue

xiandalisay commented 9 years ago

In my update function..., I notice when it comes after createMultiple(), the $model becomes empty instances. How did you solve yours?

public function actionUpdateMembers($id) { $rec = $this->findModel($id);

    $oldIDs = ArrayHelper::map($models, 'id', 'id');
    $models = Model::createMultiple(Member::classname(), $models);

        $oldIDs = ArrayHelper::map($models, 'id', 'id');
        //$models = Model::createMultiple(Member::classname(), $models);
       if( Model::loadMultiple($models, Yii::$app->request->post())){
        $deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($models, 'id', 'id')));

        // ajax validation
        if (Yii::$app->request->isAjax) {
            Yii::$app->response->format = Response::FORMAT_JSON;
            return ArrayHelper::merge(
                ActiveForm::validateMultiple($models)
                //,
                //ActiveForm::validate($rec)
            );
        }

        // validate all models
        //$valid = $rec->validate();
        $valid = Model::validateMultiple($models); // && $valid;

        if ($valid) {
            $transaction = \Yii::$app->db->beginTransaction();
            try {
                    if (! empty($deletedIDs)) {
                        Member::deleteAll(['id' => $deletedIDs]);
                    }
                    foreach ($models as $model) {
                        $model->rec_id = $rec->id;
                        if (! $model->save(false)) {
                            $transaction->rollBack();
                            break;
                        }
                    }
                if ($flag) {
                    $transaction->commit();
                    return $this->redirect(['/member/index', 'id' => $rec->id]);
                }
            } catch (Exception $e) {
                $transaction->rollBack();
            }
        }

    }
    return $this->render('/member/update', [
        'rec' => $rec,
        'models' => (empty($models)) ? [new \frontend\models\Member] : $models,
        'id'=>$id,
    ]);
}
fsc7 commented 9 years ago

Here my Update, I am sorry I can't take a look at your code right now.

    public function actionUpdate($id)
    {
      $model = $this->findModel($id);
      $modelOrderItems = $model->wholesalerOrderItems;

      if ($model->load(Yii::$app->request->post())) {
        $oldIDs = ArrayHelper::map($modelOrderItems, 'id', 'id');
        $modelOrderItems = Model::createMultiple(WholesalerOrderItem::classname(), $modelOrderItems);
        Model::loadMultiple($modelOrderItems, Yii::$app->request->post());
        $deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelOrderItems, 'id', 'id')));

        // validate all models
        $valid = $model->validate();
        $valid = Model::validateMultiple($modelOrderItems) && $valid;
        $arrived=0;
        $all_moved_to_stock=0;
        if ($model->status_id==$model::STATUS_ARRIVED){
          $arrived=1;
          $all_moved_to_stock=1;
          $stocks=array();
        }

        if ($valid) {
            $transaction = \Yii::$app->db->beginTransaction();
            try {
                if ($flag = $model->save(false)) {
                    if (! empty($deletedIDs)) {
                        WholesalerOrderItem::deleteAll(['id' => $deletedIDs]);
                    }
                    foreach ($modelOrderItems as $modelOrderItem) {
                        $modelOrderItem->order_id = $model->id;
                        if ($model->status_id != $model::STATUS_ARRIVED){
                          $modelOrderItem->status_id = $modelOrderItem::STATUS_PENDING;
                        }
                        if (! ($flag = $modelOrderItem->save(false))) {
                            $transaction->rollBack();
                            break;
                        }
                        if ($arrived && ($modelOrderItem->status_id!=$modelOrderItem::STATUS_MOVED_TO_STOCK)){
                          $all_moved_to_stock=0;
                        } else {
                          $stock = new Stock();
                          $stock->wholesaler_order_item_id = $modelOrderItem->id;
                          $stock->product_id = $modelOrderItem->product_id;
                          $stock->quantity = $modelOrderItem->quantity;
                          $stock->date = date("Y-m-d H:i:s");
                          $stock->type = 'in';
                          if ($stock->validate()){
                            $stocks[]=$stock;
                          } else {
                            Yii::error("Error in validation");
                          }
                        }
                      }
                      if ($all_moved_to_stock){
                        foreach($stocks as $stock){
                          $stock->save();
                        }
                        $model->status_id = $model::STATUS_COMPLETED;
                        $model->save();
                        Yii::info("Order Completed");
                      }
                  }
                  if ($flag) {
                      $transaction->commit();
                      //return $this->redirect(['view', 'id' => $model->id]);
                  }
                } catch (Exception $e) {
                $transaction->rollBack();
                }
              }
          }
        return $this->render('update', [
            'model' => $model,
            'modelOrderItems' => (empty($modelOrderItems)) ? [new WholesalerOrderItem] : $modelOrderItems
        ]);
    }
epulgaron commented 9 years ago

plz!!! i want two dynamic forms in one view, how is the _controller to do that?

vishwasrao commented 8 years ago

Hi All, My update is also working fine. Below are steps followed for same:

  1. My tables are po ,Corresponding Model is Po poitem, Corresponding Model is Poitem Please note I have created modules po , poitem and then created models inside it. so please make your changes accordingly.

As mentioned in video there should be relationship between po & poitem.

  1. Add 'modelsPoitem' =>$modelsPoitem, in your update.php of po.
  2. Add "use backend\modules\poitem\models\Poitem;" (without quotes ) in your Po.php

Here is my update section for PoController

public function actionUpdate($id)
    {
        $model = $this->findModel($id);
        $modelsPoitem = $model->poitems; 
//This name poitems is very important,I am not sure but it seems relationship name,because I got //error while doing related to relationship
        if ($model->load(Yii::$app->request->post()) && $model->save()) {
             $oldIDs = ArrayHelper::map($modelsPoitem, 'id', 'id');
            $modelsPoitem = Model::createMultiple(Poitem::classname(), $modelsPoitem);
            Model::loadMultiple($modelsPoitem, Yii::$app->request->post());
            $deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelsPoitem, 'id', 'id')));            
            // validate all models
            $valid = $model->validate();
            $valid = Model::validateMultiple($modelsPoitem) && $valid;
            if ($valid) {
                $transaction = \Yii::$app->db->beginTransaction();
                try {
                    if ($flag = $model->save(false)) {
                        if (! empty($deletedIDs)) {
                            Poitem::deleteAll(['id' => $deletedIDs]);
                        }
                        foreach ($modelsPoitem as $modelPoitem) {
                            $modelPoitem->po_id = $model->id;
                            if (! ($flag = $modelPoitem->save(false))) {
                                $transaction->rollBack();
                                break;
                            }
                        }
                    }
                    if ($flag) {
                        $transaction->commit();
                        return $this->redirect(['view', 'id' => $model->id]);
                    }
                } catch (Exception $e) {
                    $transaction->rollBack();
                }
            }   
        } else {
            return $this->render('update', [
                'model' => $model,
                 'modelsPoitem' => (empty($modelsPoitem)) ? [new Poitem] : $modelsPoitem
            ]);
        }
    }
halefomtekle commented 8 years ago

Thanks you all, i have solved my problem on actionUpdate

epulgaron commented 8 years ago

vishwasrao My question is that I have to use more than two dynamic form in a single view. For single dynamic widget it works fine while saving from controller but others are saving just the last data of dynamic widget, while inspecting the post data in network array index for others except first dynamic form are not increasing (there index is only zero). Would you please suggest how should I have to do. How can I use multiple dynamic-form widget in single view. Thank you in advance.

vishwasrao commented 8 years ago

Hi epulgaron, If I am getting your issue correctly.You want 2 dynamic form widgets in single model. let say in Invoice form ,you want: 1: invoiceitem dynamic widget 2:serviceitem dynamic widget. As you say your one dynamic form is working properly . Please create new function in Model.php similar to createMultiple & try by using that. Also give code snippet for your controller & form .I will check & update on same.

epulgaron commented 8 years ago

no, i have Planificacion ,it has a relationship hasMany with Modelo03 and with Modelo04, so when i create only Planificacion works great, if i create just one of modelo03 and 04 works fine too, but if i create more than one modelo03 and 04 only save the last one each, i need to save mor than one , so how can i fix it? i'm use your project and i see that it works for Po and PoItem, but in my case don't, plz help

epulgaron commented 8 years ago

Hy vishwasrao, here is my _form and my controller _form

<?php

use yii\helpers\Html;
//use yii\widgets\ActiveForm;
use wbraganca\dynamicform\DynamicFormWidget;
use backend\models\Model;
use backend\models\Modelo01;
use backend\models\Modelo03;
use yii\helpers\ArrayHelper;
use kartik\widgets\Select2;
//  use yii\jui\DatePicker;
use yii\helpers\Url;
use yii\bootstrap\ActiveForm;
use kartik\widgets\DatePicker;
use kartik\datecontrol\DateControl;

/* @var $this yii\web\View */
/* @var $model backend\models\Planificacion */
/* @var $form yii\widgets\ActiveForm */
?>

<div class="planificacion-form">

    <?php $form = ActiveForm::begin(['id' => 'dynamic-form','layout'=>'horizontal']); ?>

    <?= $form->field($model, 'plan_cod')->textInput(['maxlength' => 255,'style'=>'width:250px;']) ?>

    <?= $form->field($model, 'plan_desc')->textarea(['maxlength' => 5000,'style'=>'width:250px;']) ?>

    <?= $form->field($model, 'plan_acc_extra')->checkbox(array('value' => 'Si', 'uncheck' => 'No')) ?>

    <?= $form->field($model, 'orga_fk')->widget(Select2::classname(), [
        'data' => ArrayHelper::map(\backend\models\Norganismos::find()->asArray()->all(), 'id_orga', 'orga_siglas'),
        'options' => ['placeholder' => 'Seleccione un organismo','style'=>'width:250px;',
            'onchange'=>'
                        $.get( "'.Url::toRoute('/planificacion/lists').'", { id: $(this).val() } )
                            .done(function( data ) {
                                $( "#'.Html::getInputId($model, 'entidad_fk').'" ).html( data );
                            }
                        );
                    '],
        'pluginOptions' => [
        'allowClear' => true
        ],
        ]); ?>

    <?= $form->field($model, 'entidad_fk')->widget(Select2::classname(), [
        'data' => ArrayHelper::map(\backend\models\Entidad::find()->asArray()->all(), 'id_entidad', 'entidad_nombre'),
        'options' => ['placeholder' => 'Seleccione una entidad','style'=>'width:250px;'],
        'pluginOptions' => [
        'allowClear' => true
        ],
        ]); ?>

    <?= $form->field($model, 'tipo_accion_fk')->widget(Select2::classname(), [
        'data' => ArrayHelper::map(\backend\models\Ntipoaccion::find()->asArray()->all(), 'id_tipo_accion', 'tipo_acc_desc'),
        'options' => ['placeholder' => 'Seleccione un tipo de acción ','style'=>'width:250px;'],
        'pluginOptions' => [
        'allowClear' => true
        ],
        ]); ?>

    <?= $form->field($model, 'particularidades_fk')->widget(Select2::classname(), [
        'data' => ArrayHelper::map(\backend\models\Nparticularidades::find()->asArray()->all(), 'id_particularidades', 'particularidades_desc'),
        'options' => ['placeholder' => 'Seleccione una particularidad ','style'=>'width:250px;'],
        'pluginOptions' => [
        'allowClear' => true
        ],
        ]); ?>

    <?= $form->field($model, 'plan_fecha_inicio')->widget(DatePicker::classname(), [
    'model' => $model,
    'attribute' => 'plan_fecha_inicio',
    'options'=>['placeholder'=>'Inserte una fecha','style'=>'width:250px;'],
    'language' => 'es',
    'pluginOptions' => [
    'dateFormat' => 'yy-mm-dd',
     ],
    //'dateFormat' => 'yyyy-MM-dd',
    ]); ?>

    <?= $form->field($model, 'plan_fecha_fin')->widget(DatePicker::classname(), [
    'model' => $model,
    'attribute' => 'plan_fecha_fin',
    'options'=>['placeholder'=>'Inserte una fecha','style'=>'width:250px;'],
    'language' => 'es',
    'pluginOptions' => [
    'dateFormat' => 'yy-mm-dd',
     ],
    //'dateFormat' => 'yyyy-MM-dd',
    ]); ?>

    <?= $form->field($model, 'plan_cant_aut')->textInput(['style'=>'width:250px;']) ?>

    <?= $form->field($model, 'plan_cant_dias')->textInput(['style'=>'width:250px;']) ?>

    <?= $form->field($model, 'conclusion_fk')->widget(Select2::classname(), [
        'data' => ArrayHelper::map(\backend\models\Nconclusiones::find()->asArray()->all(), 'id_conclusion', 'conclusion_desc'),
        'options' => ['placeholder' => 'Seleccione un estado ','style'=>'width:250px;'],
        'pluginOptions' => [
        'allowClear' => true
        ],
        ]); ?>

    <?= $form->field($model, 'dic_fk')->textInput(['maxlength' => true]) ?>

    <?= $form->field($model, 'plan_reg_por')->textInput(['maxlength' => true]) ?>

  <div class="row">
        <div class="panel panel-default">
        <div class="panel-heading"><h4><i class="glyphicon glyphicon-envelope"></i> Modelo 01</h4></div>
        <div class="panel-body">
             <?php DynamicFormWidget::begin([
                'widgetContainer' => 'dynamicform_wrapper', // required: only alphanumeric characters plus "_" [A-Za-z0-9_]
                'widgetBody' => '.container-items', // required: css class selector
                'widgetItem' => '.item', // required: css class
                'limit' => 1, // the maximum times, an element can be cloned (default 999)
                'min' => 0, // 0 or 1 (default 1)
                'insertButton' => '.add-item', // css class
                'deleteButton' => '.remove-item', // css class
                'model' => $modelsModelo01[0],
                'formId' => 'dynamic-form',
                'formFields' => [
                    'plan_orden',
                    'modelo01_directiva',
                    'modelo01_fecha_ini_real',
                    'modelo01_fecha_fin_real',
                    'calificacion_fk',
                    'modelo01_cant_aud_real',
                    'modelo01_dias_real',
                    'modelo01_phc',
                    'modelo01_phd',
                    'dic_fk',                    
                ],
            ]); ?>

            <div class="panel panel-default">
        <div class="panel-heading">
            <h4>
                <i class="glyphicon glyphicon-envelope"></i> 
                <button type="button" class="add-item btn btn-success btn-sm pull-right"><i class="glyphicon glyphicon-plus"></i> Insertar</button>
            </h4>
        </div>
        <div class="panel-body">
            <div class="container-items"><!-- widgetBody -->
            <?php foreach ($modelsModelo01 as $i => $modelModelo01): ?>
                <div class="item panel panel-default"><!-- widgetItem -->
                    <div class="panel-heading">
                        <h3 class="panel-title pull-left"></h3>
                        <div class="pull-right">
                            <button type="button" class="remove-item btn btn-danger btn-xs"><i class="glyphicon glyphicon-minus"></i></button>
                        </div>
                        <div class="clearfix"></div>
                    </div>
                    <div class="panel-body">
                        <?php
                            // necessary for update action.
                            if (! $modelModelo01->isNewRecord) {
                                echo Html::activeHiddenInput($modelModelo01, "[{$i}]planificacion_fk");
                            }
                        ?>
                        <?= $form->field($modelModelo01, "[{$i}]plan_orden")->textInput(['maxlength' => 255,'style'=>'width:250px;']) ?>
                        <div class="row">
                            <div class="col-sm-6">
                                <?= $form->field($modelModelo01, "[{$i}]modelo01_directiva")->textInput(['maxlength' => 255,'style'=>'width:250px;']) ?>
                            </div>
                            <div class="col-sm-6">
                                <?= $form->field($modelModelo01, "[{$i}]modelo01_fecha_ini_real")->widget(DatePicker::classname(), [
                                    'model' => $modelModelo01,
                                    'attribute' => 'modelo01_fecha_ini_real',
                                    'options'=>['placeholder'=>'Inserte una fecha','style'=>'width:250px;'],
                                    'language' => 'es',
                                    'pluginOptions' => [
                                    'dateFormat' => 'yyyy-MM-dd',
                                     ],
                                    ]); 
                                ?>
                            </div>
                        </div><!-- .row -->
                        <div class="row">
                            <div class="col-sm-4">
                                <?= $form->field($modelModelo01, "[{$i}]modelo01_fecha_fin_real")->widget(DatePicker::classname(), [
                                'model' => $modelModelo01,
                                'attribute' => 'modelo01_fecha_fin_real',
                                'options'=>['placeholder'=>'Inserte una fecha','style'=>'width:250px;'],
                                'language' => 'es',
                                'pluginOptions' => [
                                'dateFormat' => 'yyyy-MM-dd',
                                 ],
                                ]); ?>
                            </div>
                            <div class="col-sm-4">
                                <?= $form->field($modelModelo01, "[{$i}]calificacion_fk")->widget(Select2::classname(), [
                                    'data' => ArrayHelper::map(\backend\models\Ncalificaciones::find()->asArray()->all(), 'id_calificacion', 'calificacion_desc'),
                                    'options' => ['placeholder' => 'Seleccione una calificación ','style'=>'width:250px;'],
                                    'pluginOptions' => [
                                    'allowClear' => true
                                    ],
                                    ]); ?>
                            </div>
                            <div class="col-sm-4">
                                <?= $form->field($modelModelo01, "[{$i}]modelo01_cant_aud_real")->textInput(['style'=>'width:250px;']) ?>
                            </div>
                        </div><!-- .row -->
                        <div class="row">
                            <div class="col-sm-4">
                                <?= $form->field($modelModelo01, "[{$i}]modelo01_dias_real")->textInput(['style'=>'width:250px;']) ?>
                            </div>
                            <div class="col-sm-4">
                                <?= $form->field($modelModelo01, "[{$i}]modelo01_phc")->textInput(['style'=>'width:250px;']) ?>
                            </div>
                            <div class="col-sm-4">
                                <?= $form->field($modelModelo01, "[{$i}]modelo01_phd")->textInput(['style'=>'width:250px;']) ?>
                            </div>
                        </div><!-- .row -->
                        <div class="row">
                            <div class="col-sm-4">
                                <?= $form->field($modelModelo01, "[{$i}]dic_fk")->textInput(['maxlength' => 255,'style'=>'width:250px;']) ?>
                            </div>
                        </div><!-- .row -->
                    </div>
                </div>
            <?php endforeach; ?>
            </div>
        </div>
    </div><!-- .panel -->
    <?php DynamicFormWidget::end(); ?>
 </div>
</div>
</div>

<div class="row">
        <div class="panel panel-default">
        <div class="panel-heading"><h4><i class="glyphicon glyphicon-envelope"></i> Modelo 03</h4></div>
        <div class="panel-body">
             <?php DynamicFormWidget::begin([
                'widgetContainer' => 'dynamicform_wrapper', // required: only alphanumeric characters plus "_" [A-Za-z0-9_]
                'widgetBody' => '.container-items2', // required: css class selector
                'widgetItem' => '.item2', // required: css class
                'limit' => 999, // the maximum times, an element can be cloned (default 999)
                'min' => 0, // 0 or 1 (default 1)
                'insertButton' => '.add-item2', // css class
                'deleteButton' => '.remove-item2', // css class
                'model' => $modelsModelo03[0],
                'formId' => 'dynamic-form',
                'formFields' => [
                    'cargo_fk',
                    'medida_apl_fk',
                    'modelo03_cant',
                    'dic_fk',                   
                ],
            ]); ?>

            <div class="panel panel-default">
        <div class="panel-heading">
            <h4>
                <i class="glyphicon glyphicon-envelope"></i> 
                <button type="button" class="add-item2 btn btn-success btn-sm pull-right"><i class="glyphicon glyphicon-plus"></i> Insertar</button>
            </h4>
        </div>
        <div class="panel-body">
            <div class="container-items2"><!-- widgetBody -->
            <?php foreach ($modelsModelo03 as $i => $modelModelo03): ?>
                <div class="item2 panel panel-default"><!-- widgetItem -->
                    <div class="panel-heading">
                        <h3 class="panel-title pull-left"></h3>
                        <div class="pull-right">
                            <button type="button" class="remove-item2 btn btn-danger btn-xs"><i class="glyphicon glyphicon-minus"></i></button>
                        </div>
                        <div class="clearfix"></div>
                    </div>
                    <div class="panel-body">
                        <?php
                            // necessary for update action.
                            if (! $modelModelo03->isNewRecord) {
                                echo Html::activeHiddenInput($modelModelo03, "[{$i}]planificacion_fk");
                            }
                        ?>                        
                        <div class="row">
                            <div class="col-sm-6">
                                <?= $form->field($modelModelo03, "[{$i}]cargo_fk")->textInput(['maxlength' => true]) ?>
                            </div>
                            <div class="col-sm-6">
                                <?= $form->field($modelModelo03, "[{$i}]medida_apl_fk")->textInput(['maxlength' => true]) ?>
                            </div>
                        </div><!-- .row -->
                        <div class="row">
                            <div class="col-sm-4">
                                <?= $form->field($modelModelo03, "[{$i}]modelo03_cant")->textInput(['maxlength' => true]) ?>
                            </div>
                            <div class="col-sm-4">
                                <?= $form->field($modelModelo03, "[{$i}]dic_fk")->textInput(['maxlength' => true]) ?>
                            </div>
                        </div><!-- .row -->
                    </div>
                </div>
            <?php endforeach; ?>
            </div>
        </div>
    </div><!-- .panel -->
    <?php DynamicFormWidget::end(); ?>
 </div>
</div>
</div>
<div class="form-group">
        <?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
    </div>

    <?php ActiveForm::end(); ?>

controller

<?php

namespace backend\controllers;

use Yii;
use backend\models\Planificacion;
use backend\models\PlanificacionSearch;
use backend\models\Modelo01;
use backend\models\Modelo03;
use backend\models\Model;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\helpers\ArrayHelper;
use mPDF;

/**
 * PlanificacionController implements the CRUD actions for Planificacion model.
 */
class PlanificacionController extends Controller
{
    public function behaviors()
    {
        return [
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'delete' => ['post'],
                ],
            ],
        ];
    }

    /**
     * Lists all Planificacion models.
     * @return mixed
     */
    public function actionIndex()
    {
        $searchModel = new PlanificacionSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }

    /**
     * Displays a single Planificacion model.
     * @param string $id
     * @return mixed
     */
    public function actionView($id)
    {
        return $this->render('view', [
            'model' => $this->findModel($id),
        ]);
    }

    /**
     * Creates a new Planificacion model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     * @return mixed
     */
    public function actionCreate()
    {
        $model = new Planificacion();
        $modelsModelo01 = [new Modelo01];
        $modelsModelo03 = [new Modelo03];

        if ($model->load(Yii::$app->request->post()) /*&& $model->save()*/) 
        {

            $modelsModelo01 = Model::createMultiple(Modelo01::classname());
            \yii\base\Model::loadMultiple($modelsModelo01, Yii::$app->request->post());
            $modelsModelo03 = Model::createMultiple(Modelo03::classname());
            \yii\base\Model::loadMultiple($modelsModelo03, Yii::$app->request->post());   

            // validate all models
            $valid = $model->validate();
            $valid = \yii\base\Model::validateMultiple($modelsModelo01) && $valid;
            $valid1 = $model->validate();
            $valid1 = \yii\base\Model::validateMultiple($modelsModelo03) && $valid1;

            if ($valid1 && $valid1 ) {
                $transaction = \Yii::$app->db->beginTransaction();
                try {
                    if ($flag = $model->save(false)) {
                        foreach ($modelsModelo01 as $modelModelo01)
                            {
                            $modelModelo01->planificacion_fk = $model->plan_cod;
                            if (! ($flag = $modelModelo01->save(false))) {
                                $transaction->rollBack();
                                break;
                            }
                        }
                        foreach ($modelsModelo03 as $modelModelo03) 
                            {
                            $modelModelo03->planificacion_fk = $model->plan_cod;
                            if (! ($flag = $modelModelo03->save(false))) {
                                $transaction->rollBack();
                                break;
                            }
                        }         
                    }
                    if ($flag) {
                        $transaction->commit();
                        return $this->redirect(['view', 'id' => $model->plan_cod]);
                    }
                } catch (Exception $e) {
                    $transaction->rollBack();
                }
            }
        } else {
            return $this->render('create', [
                'model' => $model,
                'modelsModelo01' => (empty($modelsModelo01)) ? [new Modelo01] : $modelsModelo01,
                'modelsModelo03' => (empty($modelsModelo03)) ? [new Modelo03] : $modelsModelo03,
            ]);
        }
    }

    /**
     * Updates an existing Planificacion model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param string $id
     * @return mixed
     */
    public function actionUpdate($id)
    {
       //code
    }

    /**
     * Deletes an existing Planificacion model.
     * If deletion is successful, the browser will be redirected to the 'index' page.
     * @param string $id
     * @return mixed
     */
    public function actionDelete($id)
    {
        $this->findModel($id)->delete();

        return $this->redirect(['index']);
    }

    /**
     * Finds the Planificacion model based on its primary key value.
     * If the model is not found, a 404 HTTP exception will be thrown.
     * @param string $id
     * @return Planificacion the loaded model
     * @throws NotFoundHttpException if the model cannot be found
     */
    protected function findModel($id)
    {
        if (($model = Planificacion::findOne($id)) !== null) {
            return $model;
        } else {
            throw new NotFoundHttpException('The requested page does not exist.');
        }
    }

    public function actionLists($id)
    {
        $rows = \app\models\Entidad::find()->where(['orga_fk' => $id])->all();

        echo "<option>Selecione una entidad</option>";

        if(count($rows)>0){
            foreach($rows as $row){
                echo "<option value='$row->id_entidad'>$row->entidad_nombre</option>";
            }
        }
        else{
            echo "<option>No existe ninguna entidad</option>";
        } 
    }
}

the first work fine(Modelo01) because i need just one, but if i add one more, the kartik-select2 stop working and DatePicker stop work too and of course only save the last one, that happends with any dynamic form, thx and sorry for my bad english

Ethennoob commented 8 years ago

hey vishwasrao,your update function is no sure for me

$modelsPoitems = $model->poitems;

and it is my update function

Think your help

public function actionUpdate($id)
{
$model = $this->findModel($id);
//$modelsPoitems = $model->poitems; oh that error !!!
$modelsPoitems = Poitem::find()->where(['po_id'=>$id])->all();//it ture! :D

    if ($model->load(Yii::$app->request->post()) && $model->save()) {
        $oldIDs = ArrayHelper::map($modelsPoitems, 'id', 'id');
        $modelsPoitems = Model::createMultiple(Poitem::classname(), $modelsPoitems);
        Model::loadMultiple($modelsPoitems, Yii::$app->request->post());
        $deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelsPoitems, 'id', 'id')));

        // validate all models
        $valid = $model->validate();
        $valid = Model::validateMultiple($modelsPoitems) && $valid;

        if ($valid) {
            $transaction = \Yii::$app->db->beginTransaction();
            try {
                if ($flag = $model->save(false)) {
                    if (! empty($deletedIDs)) {
                        Poitem::deleteAll(['id' => $deletedIDs]);
                    }
                    foreach ($modelsPoitems as $modelPoitem) {
                        $modelPoitem->po_id = $model->id;
                        if (! ($flag = $modelPoitem->save(false))) {
                            $transaction->rollBack();
                            break;
                        }
                    }
                }
                if ($flag) {
                    $transaction->commit();
                    return $this->redirect(['view', 'id' => $model->id]);
                }
            } catch (Exception $e) {
                $transaction->rollBack();
            }
        }
    } else {
        return $this->render('update', [
            'model' => $model,
            'modelsPoitems'=>(empty($modelsPoitems)) ? [new Poitem] : $modelsPoitems]);
    }
}
vishwasrao commented 8 years ago

Hi, When you have relationship between po-poitems ,You generate models. then in po.php you will get

/**
     * @return \yii\db\ActiveQuery
     */
    public function getPoitems()
    {
        return $this->hasMany(Poitem::className(), ['po_id' => 'id']);
    }

so you have to use

$modelsPoitems = $model->poitems; //this name poitems comes from getPoitems name with poitems

Thanks, Vishwas

fsc7 commented 8 years ago

It would be good if you send some code...

marat-y commented 8 years ago

@epulgaron @vishwasrao same problem. Second widget saves only last item. Have you found any solution?

epulgaron commented 8 years ago

@icemall yes , the problem was that used the same 'widgetContainer' name for every one, then i changed it and problem solved, now my problem is when i trying to update, nothing happends just blank page, i leave you my actionCreate an actionUpdate, the create works great, i've 3 dynamic form and 1 nested one in the same index, any help with the actionUpdate will be welcome

actionCreate ` public function actionCreate() { $model = new Cumplimiento(); $modelsResolucion = [new Resolucion]; $modelsMedidas = [new Medidas]; $modelsDeficiencias = [new Deficiencias]; $modelsPHD = [new Phd]; $modelsImplicados = [[new Implicados]];

    if ($model->load(Yii::$app->request->post()) && $model->save())
    {
        //-----------Perjuicios economicos-----
        $modelsResolucion = Model::createMultiple(Resolucion::classname());
        Model::loadMultiple($modelsResolucion, Yii::$app->request->post());

        //-----------Medidas Aplicadas-----
        $modelsMedidas = Model::createMultiple(Medidas::classname());
        Model::loadMultiple($modelsMedidas, Yii::$app->request->post());

        //----------Principales Deficiencias-----
        $modelsDeficiencias = Model::createMultiple(Deficiencias::classname());
        Model::loadMultiple($modelsDeficiencias, Yii::$app->request->post());

        //-----------PHD----------
        $modelsPHD = Model::createMultiple(Phd::classname());
        Model::loadMultiple($modelsPHD, Yii::$app->request->post());           

        // validate all models
        $valid = $model->validate();
        $valid = (Model::validateMultiple($modelsResolucion) || Model::validateMultiple($modelsMedidas) || Model::validateMultiple($modelsDeficiencias)|| Model::validateMultiple($modelsPHD))&&$valid;

        if (isset($_POST['Implicados'][0][0])) {
            foreach ($_POST['Implicados'] as $indexPHD => $implicados) {
                foreach ($implicados as $indexImplicados => $implicado) {
                    $data['Implicados'] = $implicado;
                    $modelImplicados = new Implicados;
                    $modelImplicados->load($data);
                    $modelsImplicados[$indexPHD][$indexImplicados] = $modelImplicados;
                    $valid = $modelImplicados->validate();
                }
            }
        }

        if ($valid) {
            $transaction = \Yii::$app->db->beginTransaction();
            try {
                if ($flag = $model->save(false))
                {
                    foreach ($modelsResolucion as $modelResolucion) {
                        $modelResolucion->mod01_id = $model->codigo;
                        if (! ($flag = $modelResolucion->save(false))) {
                            $transaction->rollBack();
                            break;
                        }
                    }
                    foreach ($modelsMedidas as $modelMedidas) {
                        $modelMedidas->mod01_id = $model->codigo;
                        if (! ($flag = $modelMedidas->save(false))) {
                            $transaction->rollBack();
                            break;
                        }
                    }
                    foreach ($modelsDeficiencias as $modelDeficiencias) {
                        $modelDeficiencias->mod01_id = $model->codigo;
                        if (! ($flag = $modelDeficiencias->save(false))) {
                            $transaction->rollBack();
                            break;
                        }
                    }

                    foreach ($modelsPHD as $indexPHD => $modelPHD) {

                        if ($flag === false) {
                            break;
                        }

                        $modelPHD->mod01_id = $model->codigo;

                        if (!($flag = $modelPHD->save(false))) {
                            break;
                        }

                        if (isset($modelsImplicados[$indexPHD]) && is_array($modelsImplicados[$indexPHD])) {
                            foreach ($modelsImplicados[$indexPHD] as $indexImplicados => $modelImplicados) {
                                $modelImplicados->phd_id = $modelPHD->no_registro;
                                $modelImplicados->mod01_id = $modelPHD->mod01_id;
                                if (!($flag = $modelImplicados->save(false))) {
                                    break;
                                }
                            }
                        }
                    }
                }
                if ($flag) {
                    $transaction->commit();
                    return $this->redirect(['view', 'id' => $model->codigo]);
                }
            } catch (Exception $e) {
                $transaction->rollBack();
            }
        }
    } 
    else {
        return $this->render('create', [
            'model' => $model,
            'modelsResolucion' => (empty($modelsResolucion)) ? [new Resolucion] : $modelsResolucion,
            'modelsMedidas' => (empty($modelsMedidas)) ? [new Medidas] : $modelsMedidas,
            'modelsDeficiencias' => (empty($modelsDeficiencias)) ? [new Deficiencias] : $modelsDeficiencias,
            'modelsPHD' => (empty($modelsPHD)) ? [new Phd] : $modelsPHD,
            'modelsImplicados' => (empty($modelsImplicados)) ? [[new Implicados]] : $modelsImplicados,
        ]);
    }
}

`

actionUpdate ` public function actionUpdate($id) { $model = $this->findModel($id); $modelsResolucion = $model->resolucions; $modelsMedidas = $model->medidas; $modelsDeficiencias = $model->deficiencias; $modelsPHD = $model->phds; $modelsImplicados = []; $oldImplicados = [];

  if (!empty($modelsPHD)) {
        foreach ($modelsPHD as $indexPHD => $modelPHD) {
            $implicados = $modelPHD->implicados;
            $modelsImplicados[$indexPHD] = $implicados;
            $oldImplicados = ArrayHelper::merge(ArrayHelper::index($implicados, 'phd_id'), $oldImplicados);
        }
    }     

 if ($model->load(Yii::$app->request->post()) && $model->save())
    {
        //-----------resolucion--------------
        $oldIDsResolucion = ArrayHelper::map($modelsResolucion, 'mod01_id', 'mod01_id');
        $modelsResolucion = Model::createMultiple(Resolucion::classname(), $modelsResolucion);
        Model::loadMultiple($modelsResolucion, Yii::$app->request->post());
        $deletedIDsResolucion = array_diff($oldIDsResolucion, array_filter(ArrayHelper::map($modelsResolucion, 'mod01_id', 'mod01_id')));

        //--------medidas aplicadas--------------
        $oldIDsMedidas = ArrayHelper::map($modelsMedidas, 'mod01_id', 'mod01_id');
        $modelsMedidas = Model::createMultiple(Medidas::classname(), $modelsMedidas);
        Model::loadMultiple($modelsMedidas, Yii::$app->request->post());
        $deletedIDsMedidas = array_diff($oldIDsMedidas, array_filter(ArrayHelper::map($modelsMedidas, 'mod01_id', 'mod01_id')));

        //--------------------principales deficiencias------------------
        $oldIDsDeficiencias = ArrayHelper::map($modelsDeficiencias, 'mod01_id', 'mod01_id');
        $modelsDeficiencias = Model::createMultiple(Deficiencias::classname(), $modelsDeficiencias);
        Model::loadMultiple($modelsDeficiencias, Yii::$app->request->post());
        $deletedIDsDeficiencias = array_diff($oldIDsDeficiencias, array_filter(ArrayHelper::map($modelsDeficiencias, 'mod01_id', 'mod01_id')));

        //-----------------phd/implicados----------------------      
            // reset
            $modelsImplicados = [];

            $oldPHDIDs = ArrayHelper::map($modelsPHD, 'mod01_id', 'mod01_id');
            $modelsPHD = Model::createMultiple(app\models\Phd::classname(), $modelsPHD);
            Model::loadMultiple($modelsPHD, Yii::$app->request->post());
            $deletedPHDIDs = array_diff($oldPHDIDs, array_filter(ArrayHelper::map($modelsPHD, 'mod01_id', 'mod01_id')));

            // validate all models
            $valid = $model->validate();
            $valid = (Model::validateMultiple($modelsResolucion) || Model::validateMultiple($modelsMedidas) || Model::validateMultiple($modelsDeficiencias)|| Model::validateMultiple($modelsPHD))&&$valid;

            $implicadosIDs = [];
                if (isset($_POST['Implicados'][0][0]))
                {
                    foreach ($_POST['Implicados'] as $indexPHD => $implicados) {
                        $implicadosIDs = ArrayHelper::merge($implicadosIDs, array_filter(ArrayHelper::getColumn($implicados, 'id_implicados')));
                        foreach ($implicados as $indexImplicados => $implicado) {
                            $data['Implicados'] = $implicado;
                            $modelImplicados = (isset($implicado['phd_id']) && isset($oldImplicados[$implicado['phd_id']])) ? $oldImplicados[$implicado['phd_id']] : new Implicados;
                            $modelImplicados->load($data);
                            $modelsImplicados[$indexPHD][$indexImplicados] = $modelImplicados;
                            $valid = $modelImplicados->validate();
                        }
                    }
                }

            $oldImplicadosIDs = ArrayHelper::getColumn($oldImplicados, 'phd_id');
            $deletedImplicadosIDs = array_diff($oldImplicadosIDs, $implicadosIDs);

            if ($valid) {
                $transaction = \Yii::$app->db->beginTransaction();
                try {
                    if ($flag = $model->save(false)) {
                        if (!empty($oldIDsResolucion)) {
                            Resolucion::deleteAll(['mod01_id' => $deletedIDsResolucion]);
                        }
                        foreach ($modelsResolucion as $modelResolucion) {
                            $modelResolucion->mod01_id = $model->codigo;
                            if (! ($flag = $modelResolucion->save(false))) {
                                $transaction->rollBack();
                                break;
                            }
                        }
                        if (!empty($oldIDsMedidas)) {
                            Medidas::deleteAll(['mod01_id' => $deletedIDsMedidas]);
                        }
                        foreach ($modelsMedidas as $modelMedidas) {
                            $modelMedidas->mod01_id = $model->codigo;
                            if (! ($flag = $modelMedidas->save(false))) {
                                $transaction->rollBack();
                                break;
                            }
                        }
                        if (!empty($oldIDsDeficiencias)) {
                            Deficiencias::deleteAll(['mod01_id' => $deletedIDsDeficiencias]);
                        }
                        foreach ($modelsDeficiencias as $modelDeficiencias) {
                            $modelDeficiencias->mod01_id = $model->codigo;
                            if (! ($flag = $modelDeficiencias->save(false))) {
                                $transaction->rollBack();
                                break;
                            }
                        }

                        if (! empty($deletedImplicadosIDs)) {
                            Implicados::deleteAll(['phd_id' => $deletedImplicadosIDs]);
                        }

                        if (! empty($deletedPHDIDs)) {
                            Phd::deleteAll(['mod01_id' => $deletedPHDIDs]);
                        }

                        foreach ($modelsPHD as $indexPHD => $modelPHD) {

                            if ($flag === false) {
                                break;
                            }

                            $modelPHD->mod01_id = $model->codigo;

                            if (!($flag = $modelPHD->save(false))) {
                                break;
                            }

                            if (isset($modelsImplicados[$indexPHD]) && is_array($modelsImplicados[$indexPHD])) {
                                foreach ($modelsImplicados[$indexPHD] as $indexImplicados => $modelImplicados) {
                                    $modelImplicados->phd_id = $modelPHD->no_registro;
                                    $modelImplicados->mod01_id = $modelPHD->mod01_id;
                                    if (!($flag = $modelImplicados->save(false))) {
                                        break;
                                    }
                                }
                            } 
                        } 
                    }
                    if ($flag) {
                        $transaction->commit();
                        return $this->redirect(['view', 'id' => $model->codigo]);
                    }
                    else {
                    $transaction->rollBack();
                    }
                } catch (Exception $e) {
                    $transaction->rollBack();
                }
            }

    else {
        return $this->render('update', [
            'model' => $model,
            'modelsResolucion' => (empty($modelsResolucion)) ? [new Resolucion] : $modelsResolucion,
            'modelsMedidas' => (empty($modelsMedidas)) ? [new Medidas] : $modelsMedidas,
            'modelsDeficiencias' => (empty($modelsDeficiencias)) ? [new Deficiencias] : $modelsDeficiencias,
            'modelsPHD' => (empty($modelsPHD)) ? [new Phd] : $modelsPHD,
            'modelsImplicados' => (empty($modelsImplicados)) ? [[new Implicados]] : $modelsImplicados
        ]);
    }
  }
}

`

marat-y commented 8 years ago

Thank you @epulgaron, it helped!

epulgaron commented 8 years ago

@vishwasrao could you help me with my actionUpdate?

epulgaron commented 8 years ago

i see that the mistake is here: $modelsMedidas = Model::createMultiple(Medidas::classname(), $modelsMedidas);

when i use createMultiple in actionUpdate brings me this error: PHP Warning – yii\base\ErrorException

array_combine(): Both parameters should have an equal number of elements

any help will be welcome

stefanus92 commented 8 years ago

@epulgaron use something like that.. $modelsMedidas = \backend\models\Model::createMultiple(Medidas::classname(), $modelsMedidas);

dekfun06 commented 8 years ago

update is not working. Error: Getting unknown property: app\models\DentaList::id Help me.

Controller

public function actionUpdate($id) { $model = $this->findModel($id); $modelsDentalist = $model->dentaLists;

    if ($model->load(Yii::$app->request->post()) && $model->save()) {
        $oldIDs = ArrayHelper::map($modelsDentalist, 'id', 'id');
        $modelsDentalist = Model::createMultiple(DentaList::classname(), $modelsDentalist);
        Model::loadMultiple($modelsDentalist, Yii::$app->request->post());
        $deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelsDentalist, 'id', 'id')));

        // validate all models
        $valid = $model->validate();
        $valid = Model::validateMultiple($modelsDentalist) && $valid;

        if ($valid) {
            $transaction = \Yii::$app->db->beginTransaction();
            try {
                if ($flag = $model->save(false)) {
                    if (!empty($deletedIDs)) {
                        DentaList::deleteAll(['denta_id' => $deletedIDs]);
                    }
                    foreach ($modelsDentalist as $modelDentalist) {
                        $modelDentalist->denta_id = $model->denta_id;
                        if (!($flag = $modelDentalist->save(false))) {
                            $transaction->rollBack();
                            break;
                        }
                    }
                }
                if ($flag) {
                    $transaction->commit();
                    return $this->redirect(['view', 'id' => $model->denta_id]);
                }
            } catch (Exception $e) {
                $transaction->rollBack();
            }
        }
    } else {
        return $this->render('update', [
                    'model' => $model,
                    'modelsDentalist' => (empty($modelsDentalist)) ? [new DentaList] : $modelsDentalist
        ]);
    }
}

_from

<?php

use yii\helpers\Html; use yii\widgets\ActiveForm; use wbraganca\dynamicform\DynamicFormWidget; use yii\helpers\ArrayHelper; use app\models\School; use app\models\SchoolClass; use app\models\SchoolTerm; use app\models\Year;

?>

<?php $form = ActiveForm::begin(['id' => 'dynamic-form']); ?>

                <?php
                DynamicFormWidget::begin([
                    'widgetContainer' => 'dynamicform_wrapper', // required: only alphanumeric characters plus "_" [A-Za-z0-9_]
                    'widgetBody' => '.container-items', // required: css class selector
                    'widgetItem' => '.item', // required: css class
                    'limit' => 4, // the maximum times, an element can be cloned (default 999)
                    'min' => 1, // 0 or 1 (default 1)
                    'insertButton' => '.add-item', // css class
                    'deleteButton' => '.remove-item', // css class
                    'model' => $modelsDentalist[0],
                    'formId' => 'dynamic-form',
                    'formFields' => [
                        'school_class_id',
                        'student_total',
                        'deciduous_caries',
                        'permanent_no',
                        'permanent_caries',
                        'gingivitis',
                        'disorder',

                    ],
                ]);
                ?>

                    <?php foreach ($modelsDentalist as $i => $modelDentalist): ?>

                                <?php
                                //necessary for update action.
                                if (!$modelDentalist->isNewRecord) {
                                    echo Html::activeHiddenInput($modelDentalist, "[{$i}]id");
                                }
                                ?>

                                        <?=
                                        $form->field($modelDentalist, "[{$i}]school_class_id")->dropDownList(
                                                ArrayHelper::map(SchoolClass::find()
                                                                ->where("school_class_id IN(1,2,3)")
                                                                ->all(), 'school_class_id', 'school_class_name')
                                                , ['prompt' => 'เลือกรายการ...'])
                                        ?>

                                        <?= $form->field($modelDentalist, "[{$i}]student_total")->textInput(['maxlength' => true]) ?>

                                        <?= $form->field($modelDentalist, "[{$i}]deciduous_caries")->textInput(['maxlength' => true]) ?>

                                        <?= $form->field($modelDentalist, "[{$i}]permanent_no")->textInput(['maxlength' => true]) ?>

                                        <?= $form->field($modelDentalist, "[{$i}]permanent_caries")->textInput(['maxlength' => true]) ?>

                                        <?= $form->field($modelDentalist, "[{$i}]gingivitis")->textInput(['maxlength' => true]) ?>

                                        <?= $form->field($modelDentalist, "[{$i}]disorder")->textInput(['maxlength' => true]) ?>

                    <?php endforeach; ?>

                <?php DynamicFormWidget::end(); ?>

        <?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', [ 'class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>

    <?php ActiveForm::end(); ?>     

Model/Denta

public function attributeLabels() { return [ 'denta_id' => Yii::t('app', 'Denta ID'), 'school_id' => Yii::t('app', 'school'), 'school_term_id' => Yii::t('app', 'term'), 'year' => Yii::t('app', 'year'), ]; }

Model/DentaList

public function attributeLabels() { return [ 'denta_list_id' => Yii::t('app', 'Denta List ID'), 'denta_id' => Yii::t('app', 'Denta ID'), 'school_class_id' => Yii::t('app', 'class'), 'student_total' => Yii::t('app', 'student total'), 'deciduous_caries' => Yii::t('app', 'deciduous caries'), 'permanent_no' => Yii::t('app', 'permanent no'), 'permanent_caries' => Yii::t('app', 'permanent caries'), 'gingivitis' => Yii::t('app', 'gingivitis'), 'disorder' => Yii::t('app', 'disorder'), 'teacher' => Yii::t('app', 'teacher'), 'create_at' => Yii::t('app', 'Create At'), 'update_at' => Yii::t('app', 'Update At'), ]; }

Pransh20 commented 8 years ago

Hi In the update action of controller you declare $modelOrderItems = $model->wholesalerOrderItems; you just added 's' in models name,

when i do this it says accessing unknown property of the model on the second line itself, did you save anything in parent database or anything

Please let me know.

fsc7 commented 8 years ago

If you have in the Model class one function like:

    public function getWholesalerOrderItems()
    {
        return $this->hasMany(WholesalerOrderItem::className(), ['product_id' => 'id']);
    }

so you call, like I did, all order items...

Pransh20 commented 8 years ago

It Worked, it updates the new items but it does not show the previous ones to delete

does it show in you case the sub items you created first in the update version in order to delete the previous ones??

or i can only add new ones to update the sub items?

fsc7 commented 8 years ago

Yes it shows. Try to debug this part

        $oldIDs = ArrayHelper::map($modelOrderItems, 'id', 'id');
        print_r($oldIDs);
        $modelOrderItems = Model::createMultiple(WholesalerOrderItem::classname(), $modelOrderItems);
        Model::loadMultiple($modelOrderItems, Yii::$app->request->post());
        $deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelOrderItems, 'id', 'id')));
Pransh20 commented 8 years ago

It deletes all the previous created subitems, but does not show specifically what to delete

is it visible in your case when you call update() ??

fsc7 commented 8 years ago

Maybe I misunderstood your point. Can you send me some screenshot or describe better what you want?

Pransh20 commented 8 years ago

When i Create i add two members create

it gets saved in database

When i call update i get this and the previous two items are deleted i want to show those previous values also like all other fields, right now it deletes both of them is it possible ?? or does it happen with you currently? update

fsc7 commented 8 years ago

Yes, something wrong is happening there.

On this part

                if ($flag = $model->save(false)) {
                    if (! empty($deletedIDs)) {
                        WholesalerOrderItem::deleteAll(['id' => $deletedIDs]);
                    }

Try to see why your variable $deletedIDs is getting the values you already added.

Pransh20 commented 8 years ago

I am not able to locate it, i did exactly the same, parent table has column id and child has bid

below are the codes for create and update, if you can help me please

s1

and update is

s2

Pransh20 commented 8 years ago

$oldIDs = ArrayHelper::map($modelOrderItems, 'id', 'id');

$deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelOrderItems, 'id', 'id')));

can you please explain me the meaning of these two lines? why id and id in both cases and not order_id??

fsc7 commented 8 years ago
      if ($model->load(Yii::$app->request->post())) {
        $oldIDs = ArrayHelper::map($modelOrderItems, 'id', 'id');
        $modelOrderItems = Model::createMultiple(WholesalerOrderItem::classname(), $modelOrderItems);
        Model::loadMultiple($modelOrderItems, Yii::$app->request->post());
        $deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelOrderItems, 'id', 'id')));

You will get from the array_diff the items which existed before and do not exist anymore, which means they need to be deleted on database. ArrayHelper::map is only saying that you are going to have one array which has the same value (id) for key and for value. [1]=>1, [2]=>2 ....

Pransh20 commented 8 years ago

fixed i was missing a very basic line if ($model->load(Yii::$app->request->post()))

it was not checking and creating a new object always Thanks a lot :)

tanmay20 commented 8 years ago

I'm still stuck in update. Can anyone have a look here - http://stackoverflow.com/questions/39188969/yii2-dynamic-form-updating-only-one-table

bhattaxay commented 7 years ago

I'm also stuck in update module at:

public function actionUpdate($id)
    {
        $model = $this->findModel($id);
        $modelsPoItem = $model->poitem;

Please give the solution if you have .

It show the Error msg: Getting unknown property: backend\models\Po::poItem

shadrakandrea commented 6 years ago

Sorry i want to ask about this part of your source code. actionUpdate($id) { $model = $this->findModel($id); $modelOrderItems = $model->wholesalerOrderItems;

I dont know from where wholesalerOrderItems came. Please explain to me.

fsc7 commented 6 years ago

As commented before here goes the code in the model.

If you have in the Model class one function like:

    public function getWholesalerOrderItems()
    {
        return $this->hasMany(WholesalerOrderItem::className(), ['product_id' => 'id']);
    }

so you call, like I did, all order items...

shadrakandrea commented 6 years ago

Thanks fsc7.

But now i get a new problem. My update page is blank. Just a blank page and nothing happen.

fsc7 commented 6 years ago

Hello, I suppose you have a class WholesalerOrderItem and objects in it. I don't know your system and you did not give any other info, so I can't help you.

shadrakandrea commented 6 years ago

this my action update. public function actionUpdate($id) { $model = $this->findModel($id); $modelsDetail = $model->details;

    if ($model->load(Yii::$app->request->post()) && $model->save()) 
    {
        $oldIDs = ArrayHelper::map($modelsDetail, 'idorder', 'idorder');
        $modelsDetail = Model::createMultiple(Detailorder::classname(), $modelsDetail);
        if (Model::loadMultiple($modelsDetail, Yii::$app->request->post())){
        $deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelsDetail, 'idorder', 'idorder')));

        // validate all models
        $valid = $model->validate();
        $valid = Model::validateMultiple($modelsDetail) && $valid;

        if ($valid) {
            $transaction = \Yii::$app->db->beginTransaction();
            try {
                    if (! empty($deletedIDs)) {
                        Detailorder::deleteAll(['idorder' => $deletedIDs]);
                    }
                    foreach ($modelsDetail as $modelDetail) {
                        $modelDetail->idorder = $model->idorder;
                        if (! ($flag = $modelDetail->save(false))) {
                            $transaction->rollBack();
                            break;
                }
                    }
                if ($flag) {
                    $transaction->commit();
                    return $this->redirect(['view', 'id' => $model->idorder]);
                }
            } catch (Exception $e) {
                $transaction->rollBack();
            }
        }
    }return $this->render('update', [
            'model' => $model,
            'modelsDetail' => (empty($modelsDetail)) ? [new Detailorder] : $modelsDetail,
            'idorder'=> $id,
        ]);
    }
}

And this my model. I already add this code to my Model. public function getDetails() { return $this->hasMany(Detailorder::className(), ['idorder' => 'idorder']); } help me with this problem. still the same problem, blank page in my update.

fsc7 commented 6 years ago

what happens when you print $modelsDetail variable?

shadrakandrea commented 6 years ago

I should get the value from detail order table, but now i got nothing

fsc7 commented 6 years ago

So you must check why your class is not connecting properly with your database and retrieving the correct data.

fsc7 commented 6 years ago

My action update is above as well as others. But the problem is that your related model is not being retrieved. In my case I had an order (model and corresponding database table) and orderItem (also model and corresponding database table) which are linked with model primary key as foreign key at orderItem.