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.