Yii2中DateRangePicker取值并自动计算日期时长的实现
嘿,我来帮你搞定这个Yii2表单里的日期范围自动计算需求!下面是一步步的实现方案,涵盖了日期选择后自动算时长,还能联动已有数据做运算:
Yii2 ActiveForm + DateRangePicker 自动计算时长&联动数据实现
1. 完善后端表单代码
首先补全你的DateRangePicker组件,确保绑定正确的模型属性,同时添加用于展示计算结果的字段(比如时长天数、总金额等):
<div class="pelaksana-form"> <?php $form = ActiveForm::begin([ 'options'=>['id'=>'pelaksanaForm', 'data-pjax'=>true,] ]); ?> <label class="control-label">Range Perjalanan Dinas</label> <?= DatePicker::widget([ 'type' => DatePicker::TYPE_RANGE, 'model' => $model, 'attribute' => 'start_date', 'attribute2' => 'end_date', // 对应模型的end_date属性 'pluginOptions' => [ 'autoclose' => true, 'format' => 'yyyy-mm-dd', // 统一日期格式,避免JS解析出错 'todayHighlight' => true, ], 'options' => [ 'class' => 'date-range-input', ] ]) ?> <!-- 自动计算的日期时长(天数) --> <?= $form->field($model, 'duration_days')->textInput([ 'readonly' => true, 'placeholder' => '选择日期后自动计算' ])->label('时长(天数)') ?> <!-- 已有数据:每日补贴 --> <?= $form->field($model, 'daily_allowance')->textInput([ 'type' => 'number', 'min' => 0 ])->label('每日补贴') ?> <!-- 自动计算的总补贴 --> <?= $form->field($model, 'total_allowance')->textInput([ 'readonly' => true, 'placeholder' => '自动计算总金额' ])->label('总补贴') ?> <div class="form-group"> <?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?> </div> <?php ActiveForm::end(); ?> </div>
⚠️ 注意:你的模型(比如Pelaksana)需要包含start_date、end_date、duration_days、daily_allowance、total_allowance这些属性,若是临时字段可以定义为模型的虚拟属性。
2. 添加前端JavaScript逻辑
在视图文件底部添加JS代码,监听日期选择和已有数据的变化,自动完成计算:
<?php $script = <<< JS $(document).ready(function() { // 监听日期范围选择变化 $('.date-range-input').on('change', function() { const startDate = $('#pelaksana-start_date').val(); const endDate = $('#pelaksana-end_date').val(); const dailyAllowance = parseFloat($('#pelaksana-daily_allowance').val()) || 0; if (startDate && endDate) { // 计算包含起止日期的天数差 const start = new Date(startDate); const end = new Date(endDate); const timeDiff = Math.abs(end.getTime() - start.getTime()); const daysDiff = Math.ceil(timeDiff / (1000 * 3600 * 24)) + 1; // 填充时长字段 $('#pelaksana-duration_days').val(daysDiff); // 联动计算总补贴 $('#pelaksana-total_allowance').val((daysDiff * dailyAllowance).toFixed(2)); } else { // 清空计算结果 $('#pelaksana-duration_days').val(''); $('#pelaksana-total_allowance').val(''); } }); // 监听每日补贴变化,重新计算总金额 $('#pelaksana-daily_allowance').on('input', function() { const daysDiff = parseInt($('#pelaksana-duration_days').val()) || 0; const dailyAllowance = parseFloat($(this).val()) || 0; $('#pelaksana-total_allowance').val((daysDiff * dailyAllowance).toFixed(2)); }); }); JS; $this->registerJs($script, \yii\web\View::POS_END); ?>
3. 后端兜底验证(可选)
为了确保数据准确性,你可以在模型的beforeSave方法里添加后端计算逻辑,避免前端计算异常:
public function beforeSave($insert) { if (parent::beforeSave($insert)) { if ($this->start_date && $this->end_date) { $start = new \DateTime($this->start_date); $end = new \DateTime($this->end_date); $interval = $start->diff($end); $this->duration_days = $interval->days + 1; // 包含起止日期 $this->total_allowance = $this->duration_days * $this->daily_allowance; } return true; } return false; }
小提示
- 日期格式一定要统一,这里用
yyyy-mm-dd是为了避免JS解析不同格式日期出现错误; - 如果需要计算小时/分钟级别的时长,可以调整JS里的时间差计算逻辑;
- 因为表单启用了
data-pjax,如果PJAX刷新后JS失效,可以监听pjax:success事件重新绑定逻辑。
内容的提问来源于stack exchange,提问作者Yanuar Ihsan
相关产品推荐
相关产品推荐

