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.
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.
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
"id": "customer-name" into your input field ID
"container": ".field-customer-name" into input field div container class
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.
// 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.
$.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'));
});
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With