YII2:添加动态表单字段及其验证

时间:2022-11-24 20:20:31

I am adding dynamic form fields onChange of dropdown. Both types of fields are coming from different models and go to the database in different tables. I have already defined validation rules in models.

我正在添加动态表单字段onChange of dropdown。两种类型的字段都来自不同的模型,并在不同的表中转到数据库。我已经在模型中定义了验证规则。

But validation are not working properly. My code is as follows:

但验证工作不正常。我的代码如下:

Model :

型号:

<?php

namespace common\models;

use Yii;

/**
 * This is the model class for table "{{%membership_features}}".
 *
 * @property integer $id
 * @property string $title
 * @property string $type
 * @property integer $is_new
 * @property integer $status
 * @property integer $is_deleted
 * @property string $created_date
 * @property string $modified_date
 *
 * @property MembershipFeaturesValue[] $membershipFeaturesValues
 */
class MembershipFeatures extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */

    public $value=[];
    public static function tableName()
    {
        return '{{%membership_features}}';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['title', 'type', 'value','is_new', 'status'], 'required'],
            ['value', 'each', 'rule' => ['integer']],
            ['value', 'each', 'rule' => ['required']],
            [['is_new', 'status', 'value','is_deleted'], 'integer'],
            [['created_date', 'modified_date'], 'safe'],
            [['title', 'type'], 'string', 'max' => 255]
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => Yii::t('app', 'ID'),
            'title' => Yii::t('app', 'Title'),
            'type' => Yii::t('app', 'is boolean or value'),
            'is_new' => Yii::t('app', 'Is New'),
            'status' => Yii::t('app', 'Status'),
            'is_deleted' => Yii::t('app', 'Is Deleted'),
            'created_date' => Yii::t('app', 'Created Date'),
            'modified_date' => Yii::t('app', 'Modified Date'),
        ];
    }

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

Controller :

控制器:

<?php

namespace backend\controllers;

use Yii;
use common\models\MembershipFeatures;
use backend\models\MembershipFeaturesSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\web\Response;
use common\models\MembershipFeaturesValue;
use common\components\Helper;
/**
 * MembershipFeaturesController implements the CRUD actions for MembershipFeatures model.
 */
class MembershipFeaturesController extends Controller
{
    public function behaviors()
    {
        return [
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'delete' => ['post'],
                ],
            ],
        ];
    }

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

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

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

    /**
     * Creates a new MembershipFeatures model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     * @return mixed
     */
    public function actionCreate()
    {
        $model = new MembershipFeatures();
        $membershipPlan = \common\models\MembershipPlan::allPlans();

        if(isset($_GET['type'])){
            $model->type =$_GET['type'];
        }
        if (Yii::$app->request->isAjax  && $model->load(Yii::$app->request->post())) {

            Yii::$app->response->format = Response::FORMAT_JSON;
            return \yii\widgets\ActiveForm::validate($model);
        }

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

            if( $model->save()){   
                foreach ($membershipPlan as $key=>$value) {
                    $feature = new MembershipFeaturesValue();
                    $feature->feature_id = $model->id;
                    $feature->plan_id = $key;
                    $feature->value =$model->value[$key];
                    $feature->save();
                }
            }



            return $this->redirect(['index']);
        } 
            return $this->render('create', [
                'model' => $model,
                'membershipPlan'=>$membershipPlan,

            ]);

    }

    /**
     * Updates an existing MembershipFeatures model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param integer $id
     * @return mixed
     */
    public function actionUpdate($id)
    {    
        $membershipPlan = \common\models\MembershipPlan::allPlans();    
        $model = $this->findModel($id);

        $selected = MembershipFeaturesValue::find()->where(['feature_id'=>$model->id])->all();
        foreach ($selected as $key => $value) {
                $model->value[$value->plan_id]=$value->value;
        }    

        if(isset($_GET['type'])){
            $model->type =$_GET['type'];
        }
        if(Yii::$app->request->isAjax  && $model->load(Yii::$app->request->post())) {

            Yii::$app->response->format = Response::FORMAT_JSON;
            return \yii\widgets\ActiveForm::validate($model);
        }

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

            if( $model->save()){  

                foreach ($membershipPlan as $key=>$value) {
                    $feature = MembershipFeaturesValue::find()->where(['feature_id'=>$model->id,'plan_id'=>$key])->one();
                    $feature->value =$model->value[$key];
                    $feature->save();
                }
            }



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

        return $this->render('update', [
                'model' => $model,
                'membershipPlan'=>$membershipPlan,

            ]);

    }

    /**
     * Deletes an existing MembershipFeatures model.
     * If deletion is successful, the browser will be redirected to the 'index' page.
     * @param integer $id
     * @return mixed
     */
    public function actionDelete($id)
    {
        Helper::partialDelete('MembershipFeatures',$id);

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

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

Form :

表格:

<?php

use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\widgets\Pjax;
use yii\helpers\Url;
/* @var $this yii\web\View */
/* @var $model common\models\MembershipFeatures */
/* @var $form yii\widgets\ActiveForm */
?>

<div class="membership-features-form">

    <?php $form = ActiveForm::begin([   
    'enableAjaxValidation' => true,
    'enableClientValidation'=>true,
    'validateOnSubmit'=>true,   
    'options' => ['data-pjax'=>true]]); ?>
    <?= $form->errorSummary($model); ?>
    <?= $form->field($model, 'title')->textInput(['maxlength' => true]) ?>

    <?= $form->field($model, 'type')->dropDownList(['boolean'=>'Boolean','value'=>'Value'],
        [
        'onchange'=>'
            $.pjax.reload({
            url: "'.Url::to(['create']).'?type="+$(this).val(),
            container: "#pjax-memfeature-form",
            timeout: 1000,
            });
        ',

        'class'=>'form-control',
        'prompt' => 'Select Type Of Value'
        ]) ?>

        <?php  Pjax::begin(['id'=>'pjax-memfeature-form','enablePushState'=>false]);     ?> 
        <?php 
            if($model->type==='boolean'){
                foreach ($membershipPlan as $key => $value) {
                    echo $form->field($model, "value[$key]")->checkbox(array(
                                'label'=>"$value",
                                'labelOptions'=>array('style'=>'padding:5px;'),

                                )); 
                }    
            }
            if($model->type==='value'){
                foreach ($membershipPlan as $key => $value) {
                  echo $form->field($model, "value[$key]")->textInput()->label("$value"); 
                }
            }
        ?>

         <?php Pjax::end(); ?>        
    <?= $form->field($model, 'is_new')->dropDownList(['0'=>'No','1'=>'Yes']) ?>

    <?= $form->field($model, 'status')->dropDownList(['1'=>'Active','0'=>'Inactive']) ?>

    <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']) ?>
         <?= Html::a(Yii::t('app', 'Cancel'), ['/membership-features/'], ['class' => 'btn btn-danger']) ?>
    </div>

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

</div>

I want to validate my value field which is dynamically added when I change the type dropdown using Pjax. Please guide me a correct method for validating dynamically added form fields.

我想验证我在使用Pjax更改类型下拉列表时动态添加的值字段。请指导我验证动态添加的表单字段的正确方法。

3 个解决方案

#1


8  

Its been a month so guessing this has been solved but for reference for others like me looking for the same and to save having to step thru the framework to find the answer perhaps try something like:

它已经过了一个月,所以猜测这个问题已经解决了,但是对于像我这样的其他人来说,寻找同样的东西以及为了节省必须通过框架来寻找答案,或许尝试类似的东西:

...
use yii\helpers\Json;
...

<?php foreach ($form->attributes as $attribute) {
    $attribute = Json::htmlEncode($attribute);
    $this->registerJs("jQuery('form').yiiActiveForm('add', $attribute);");
} ?>

<?php Pjax::end(); ?>
...

Tested with regards to clientValidation and not with above question so have hacked my solution to hopefully answer above question.

测试了clientValidation而不是上面的问题所以已经破解了我的解决方案,希望能回答上述问题。

#2


1  

That didn't quite work for me I had to add these addrow and deleterow functions for my js. I ajax off to get a new row each time then inject it into the DOM after the last row.

这对我来说不太有用,我必须为我的js添加这些addrow和deleterow函数。我ajax off每次获取一个新行然后在最后一行之后将它注入DOM。

// Add the validation for said elements (without this val.validate but I had a validate not an expression error) data is a json object of the db model coming from my ajax controller action.

//为所述元素添加验证(没有这个val.validate但我有一个验证而不是表达式错误)data是来自我的ajax控制器动作的db模型的json对象。

$.each(data.attributes, function(key, val) {                
val = $.parseJSON(val);         
// The validate method is kept in expression so turn it back into a closure. 
val.validate = eval("var f = function(){ return "+val.validate.expression+";}; f() ;") ;
$('#dal-add-form').yiiActiveForm('add', val);
});

Then to remove the validation:

然后删除验证:

$.each($(this).parents('.dal-row').find('input, textarea, select'), function() {            
$('#form').yiiActiveForm('remove', $(this).attr('id'));
});     

#3


0  

Simple

简单

You should try this

你应该试试这个

<?php
    $this->registerJs('



            jQuery("#w0").yiiActiveForm("add",{
                "id": "customer-name",
                "name": "name",
                "container": ".field-customer-name",
                "input": "#customer-name",
                "error": ".help-block.help-block-error",
                "validate": function(attribute, value, messages, deferred, $form) {

                    yii.validation.required(value, messages, {
                        "message": "Name be blank bug."
                    });

                    yii.validation.string(value, messages, {
                        "message": "Name must be a string.",
                        "max": 255,
                        "tooLong": "Name should contain at most 255 characters.",
                        "skipOnEmpty": 1
                    });
                }
        });


    ');
 ?>

Changes

变化

  • w0 into your form ID

    w0到您的表单ID

  • "id": "customer-name" into your input field ID

    “id”:“customer-name”到您的输入字段ID中

  • "container": ".field-customer-name" into input field div container class

    “container”:“。field-customer-name”到输入字段div容器类中

#1


8  

Its been a month so guessing this has been solved but for reference for others like me looking for the same and to save having to step thru the framework to find the answer perhaps try something like:

它已经过了一个月,所以猜测这个问题已经解决了,但是对于像我这样的其他人来说,寻找同样的东西以及为了节省必须通过框架来寻找答案,或许尝试类似的东西:

...
use yii\helpers\Json;
...

<?php foreach ($form->attributes as $attribute) {
    $attribute = Json::htmlEncode($attribute);
    $this->registerJs("jQuery('form').yiiActiveForm('add', $attribute);");
} ?>

<?php Pjax::end(); ?>
...

Tested with regards to clientValidation and not with above question so have hacked my solution to hopefully answer above question.

测试了clientValidation而不是上面的问题所以已经破解了我的解决方案,希望能回答上述问题。

#2


1  

That didn't quite work for me I had to add these addrow and deleterow functions for my js. I ajax off to get a new row each time then inject it into the DOM after the last row.

这对我来说不太有用,我必须为我的js添加这些addrow和deleterow函数。我ajax off每次获取一个新行然后在最后一行之后将它注入DOM。

// Add the validation for said elements (without this val.validate but I had a validate not an expression error) data is a json object of the db model coming from my ajax controller action.

//为所述元素添加验证(没有这个val.validate但我有一个验证而不是表达式错误)data是来自我的ajax控制器动作的db模型的json对象。

$.each(data.attributes, function(key, val) {                
val = $.parseJSON(val);         
// The validate method is kept in expression so turn it back into a closure. 
val.validate = eval("var f = function(){ return "+val.validate.expression+";}; f() ;") ;
$('#dal-add-form').yiiActiveForm('add', val);
});

Then to remove the validation:

然后删除验证:

$.each($(this).parents('.dal-row').find('input, textarea, select'), function() {            
$('#form').yiiActiveForm('remove', $(this).attr('id'));
});     

#3


0  

Simple

简单

You should try this

你应该试试这个

<?php
    $this->registerJs('



            jQuery("#w0").yiiActiveForm("add",{
                "id": "customer-name",
                "name": "name",
                "container": ".field-customer-name",
                "input": "#customer-name",
                "error": ".help-block.help-block-error",
                "validate": function(attribute, value, messages, deferred, $form) {

                    yii.validation.required(value, messages, {
                        "message": "Name be blank bug."
                    });

                    yii.validation.string(value, messages, {
                        "message": "Name must be a string.",
                        "max": 255,
                        "tooLong": "Name should contain at most 255 characters.",
                        "skipOnEmpty": 1
                    });
                }
        });


    ');
 ?>

Changes

变化

  • w0 into your form ID

    w0到您的表单ID

  • "id": "customer-name" into your input field ID

    “id”:“customer-name”到您的输入字段ID中

  • "container": ".field-customer-name" into input field div container class

    “container”:“。field-customer-name”到输入字段div容器类中