I am using Yii 2 basic application template and for our requirement I am using yii2 dynamic form. I have a model called Attendancereportdetails. There is an attribute of this model Standard to which I have applied a custom validation rule. When the validation fails then the message gets displayed. This works well for each Standard field of the newly added dynamic form when the user creates a record (actionCreate).
But when the user wants to update a record and adds new dynamic form, then the validation messages are not displayed immediately for the Standard field which was working correctly during create. They appear after the form submission.
Below is the script tag
<script>
$(document).ready(function () {
$(window).keydown(function (event) {
if (event.keyCode == 13) {
event.preventDefault();
return false;
}
});
$(".i").each(function () {
$(this).attr("disabled", true);
});
$("#dynamic-form")[0].reset();
$(".dynamicform_studentattendance").on("afterInsert", function(e,item) {
var form = $("#dynamic-form");
var rowIndex = $(".studentattendance-item").length - 1; // Get the latest row index
var ascId = $("#attendancereport-ascid").val();
if (!ascId) {
alert("Please select an ASC center before adding a new form.");
$(item).remove(); // Remove the newly added form
}
$(item).find("select.s").each(function () {
var nameAttr = $(this).attr("name");
var idAttr = $(this).attr("id");
if (nameAttr) {
$(this).attr("name", nameAttr.replace("[0]", "[" + rowIndex + "]"));
}
if (idAttr) {
$(this).attr("id", idAttr.replace("_0", "_" + rowIndex));
}
});
$(document).on("change", "select.s", function () {
var fieldId = $(this).attr("id");
console.log("Triggering validation for field:", fieldId); // Debugging
$("#dynamic-form").yiiActiveForm("validateAttribute", fieldId);
});
setTimeout(function () {
var ascId = $("select#attendancereport-ascid").val();
console.log("Fetching students for new dynamic row, ASC ID:", ascId); // Debugging
if (ascId) {
$.post("index.php?r=student/student-lists&id=" + ascId, function (data) {
$(item).find('.i').html(data); // Ensure correct filtering
});
} else {
console.warn("ASC ID is missing, unable to filter students.");
}
}, 10);
});
$(document).on("change", ".i", function () {
var selectedStudents = [];
var currentDropdown = $(this);
$('.i').each(function () {
var studentId = $(this).val();
if (studentId) {
if (selectedStudents.includes(studentId)) {
alert('Duplicate student selection is not allowed!');
currentDropdown.val('');
return false;
} else {
selectedStudents.push(studentId);
}
}
});
});
});
</script>
Below is the form
<?php
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use yii\jui\DatePicker;
use wbraganca\dynamicform\DynamicFormWidget;
use app\models\Ascassignment;
use app\models\Asccenter;
use app\models\Academicyear;
use kartik\time\TimePicker;
use yii\helpers\ArrayHelper;
use app\models\Student;
use app\models\Attendancereportdetails;
?>
<div class="attendancereport-form">
<?php $form = ActiveForm::begin(['id' => 'dynamic-form',
'enableAjaxValidation' => true,
'enableClientValidation' => true,
'validateOnChange' => true,
'validateOnBlur' => true,
'options' => ['class' => 'disable-submit-buttons'],
]);?>
<div class="panel panel-primary " >
<div class="panel panel-heading"><font size="3"><b>Student Attendance Report</b></font></div>
<div class="row">
<div class="col-sm-4">
<?= $form->field($model, 'AcademicYearId')->dropDownList(ArrayHelper::map(Academicyear::find()->where(['DisplayStatus'=>'Enabled'])->all(),'Id','academicyear'), ['prompt' => 'Select Academic Year','onChange'=>'
var e = $(this);
$.post("index.php?r=attendancereport/standard&aid=' . '"+$("select#attendancereport-academicyearid").val()+"&ascid=' . '"+$("select#attendancereport-ascid").val()+"&sid=' . '"+e.val(),function(data){
e.closest("tr").find(".s").html(data);
});
'])?>
</div>
<div class="col-sm-4">
<?= $form->field($model, 'ASCId')->dropDownList(ArrayHelper::map(Asccenter::find()->leftJoin('ascassignment','`ascassignment`.`ASCId`=`asccenter`.`ASCId`')->where(['ascassignment.UserId' => \Yii::$app->user->identity->getonlyid()])->all(),'ASCId','ASCName'), ['prompt' => 'Select ASC Center','class'=>'form-control ascid','onChange' => '
$.post("index.php?r=student/student-lists&id=' . '"+$("select#attendancereport-ascid").val(),function(data){
$(".i").each(function(k,v)
{
$(".i").attr("disabled",false);
$(".i").html(data);
}
);
});
var e = $(this);
$.post("index.php?r=attendancereport/standard&aid=' . '"+$("select#attendancereport-academicyearid").val()+"&ascid=' . '"+$("select#attendancereport-ascid").val()+"&sid=' . '"+e.val(),function(data){
$(".s option:not(:first-child)").remove();
e.closest("tr").find(".s").html(data);
});
'
]) ?>
</div>
<div class="col-sm-4">
<?= $form->field($model, 'DateofReport')->widget(DatePicker::classname(), [
//'language' => 'ru',
'dateFormat' => 'yyyy-MM-dd',
'options' => ['class' => 'form-control picker','readOnly'=>'readOnly'],
'clientOptions'=>['changeMonth'=>false,
'changeYear'=>false,
'maxDate'=>'today',
'stepMonths'=> false,
],
]) ?>
</div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading"><font size="3"><b>Student Attendance Details</b></font></div>
<?php DynamicFormWidget::begin([
'widgetContainer' => 'dynamicform_studentattendance',
'widgetBody' => '.container-studentattendance',
'widgetItem' => '.studentattendance-item',
'limit' =>500,
'min' => 1,
'insertButton' => '.add-studentattendance',
'deleteButton' => '.remove-studentattendance',
'model' => $modelsStudentattendance[0],
'formId' => 'dynamic-form',
'formFields' => [
'StudentId',
'Standard',
'AttendanceStatus',
],
]); ?>
<table class="table table-bordered">
<thead>
<tr bgcolor='#B8B8B8'>
<th style='border: 1px solid black;'></th>
<th class ="text-center" style='border: 1px solid black;'>Student</th>
<th class ="text-center" style='border: 1px solid black;'>Standard</th>
<th class ="text-center" style='border: 1px solid black;'>Attendance Status</th>
<th class="text-center" style='border: 1px solid black;'>Action</th>
</tr>
</thead>
<tbody class="container-studentattendance">
<?php foreach ($modelsStudentattendance as $indexStudent => $modelStudentattendance): ?>
<tr class="studentattendance-item">
<td class="vcenter" style='border: 1px solid black;'>
<?php
// necessary for update action.
if (! $modelStudentattendance->isNewRecord) {
echo Html::activeHiddenInput($modelStudentattendance, "[{$indexStudent}]AttendanceReportDetailsId");
}
?>
</td>
<td style='border: 1px solid black;'>
<?= $form->field($modelStudentattendance, "[{$indexStudent}]StudentId")->label(false)->dropDownList(ArrayHelper::map(Student::find()->all(),'StudentId','StudentName'), ['prompt' => 'Select Student','class'=>'form-control i','onChange'=>'
var e = $(this);
$.post("index.php?r=attendancereport/standard&aid=' . '"+$("select#attendancereport-academicyearid").val()+"&ascid=' . '"+$("select#attendancereport-ascid").val()+"&sid=' . '"+e.val(),function(data){
e.closest("tr").find(".s").html(data);
});
']) ?>
</td>
<td style='border: 1px solid black;'>
<?php
if($model->isNewRecord)
{
echo $form->field($modelStudentattendance, "[{$indexStudent}]Standard")->label(false)->dropDownList([], [
'prompt' => 'Select Standard',
'class' => 'form-control s',
'id' => "attendancereportdetails-{$indexStudent}-standard",
]);
}
elseif(!$model->isNewRecord)
{
$standardMapping = [
0 => 'Nursery',
1 => '1st',
2 => '2nd',
3 => '3rd',
4 => '4th',
5 => '5th',
6 => '6th',
7 => '7th',
8 => '8th',
9 => '9th',
10 => '10th',
];
echo $form->field($modelStudentattendance, "[{$indexStudent}]Standard")->label(false)->dropDownList(
$standardMapping,
[
'prompt' => 'Select Standard',
'class' => 'form-control s',
'id' => "attendancereportdetails-{$indexStudent}-standard", // Ensure unique ID
]
);
}
?>
</td>
<td style='border: 1px solid black;'>
<?= $form->field($modelStudentattendance, "[{$indexStudent}]AttendanceStatus")->label(false)->dropDownList(['Present'=>'Present', 'Absent' => 'Absent'], ['prompt'=>'Select Attendance Status'])?>
</td>
<td class="text-center vcenter" style='border: 1px solid black;'>
<button type="button" class="add-studentattendance btn btn-success btn-xs"><span class="fa fa-plus"></span></button>
<button type="button" class="remove-studentattendance btn btn-danger btn-xs"><span class="fa fa-minus"></span></button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php DynamicFormWidget::end(); ?>
</div>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
<?= Html::resetButton('Reset',['class' => 'btn btn-default'])?>
</div>
<?php ActiveForm::end(); ?>
</div>