切换地点后Delivery Datepicker数据不刷新问题求助
切换地点后送货日期选择器无法即时更新屏蔽日期
场景与代码
我有两个日期选择器,用于屏蔽特定地点的闭店日期:
送货日期选择器(Delivery Date Picker)
<div class="input-group date form_datetime times" id="date_entrega"> <input type="text" placeholder="Fecha de entrega" size="16" readonly class="form-control" ng-model="reserva.fechasalida" name="date_fecha_entrega"/> <span class="input-group-btn"> <button class="btn default date-set" type="button"> <i class="fa fa-calendar"></i> </button> </span> </div>
归还日期选择器(Return Date Picker)
<div class="input-group date form_datetime times" id="date_devolucion"> <input type="text" placeholder="Fecha de devolución" size="16" readonly class="form-control" ng-model="reserva.fechaentrada" name="date_fecha_devolucion" ng-disabled="cobroOFacturaAlquiler"/> <span class="input-group-btn"> <button class="btn default date-set" type="button" ng-disabled="cobroOFacturaAlquiler"> <i class="fa fa-calendar"></i> </button> </span> </div>
Controller 代码
function getDaysClosedFromLocation(locationId) { LocationDaysService.getPeriodsDaysClosedFromLocation( locationId, function (response) { if (response.success) { $scope.periodDelivery = response.data; $scope.periodReturn = response.data; $("#date_entrega") .datepicker({ language: "es", format: "dd/mm/yyyy", autoclose: true, todayHighlight: true, orientation: "left", beforeShowDay: beforeShowDayDatePickerDelivery, }) .on("changeDate", function (ev) { $scope.configuracionCambioFechaHora("date_entrega"); }); $("#date_devolucion") .datepicker({ language: "es", format: "dd/mm/yyyy", autoclose: true, todayHighlight: true, orientation: "left", beforeShowDay: beforeShowDayDatePickerReturn, }) .on("changeDate", function (ev) { $scope.configuracionCambioFechaHora("date_devolucion"); }); } }, ); } function beforeShowDayDatePickerDelivery(date) { return beforeShowDay(date, $scope.periodDelivery); } function beforeShowDayDatePickerReturn(date) { return beforeShowDay(date, $scope.periodReturn); } function beforeShowDay(date, periods) { let day = date.getDay(); // 0 (Sunday) ... 6 (Saturday) for (let i = 0; i < periods.length; i++) { let period = periods[i]; if (date >= period.start && date <= period.end) { if (period.daysToDisable.includes(day)) { return false; // Disable this specific date } } } return true; // Enable all other dates }
问题描述
功能整体正常,但切换地点后,#date_devolucion能即时正确更新屏蔽日期,而#date_entrega无法即时更新,仅在切换月份再返回后才会生效。控制台无可见错误,推测是AngularJS更新机制相关问题。已尝试销毁重建Datepicker、调用refresh方法、判断是否已创建等方案,均无效。
原因分析
- AngularJS消化循环未触发:
LocationDaysService的回调属于异步操作,更新$scope.periodDelivery后,Angular可能未及时触发$digest循环,导致beforeShowDayDatePickerDelivery函数捕获的还是旧的$scope.periodDelivery值。 - 重复初始化冲突:每次切换地点都重新调用
datepicker()初始化,可能导致#date_entrega的datepicker实例存在多个配置,旧的beforeShowDay逻辑未被覆盖。 - 闭包捕获旧值:
beforeShowDayDatePickerDelivery作为闭包,可能在第一次初始化时就绑定了旧的$scope.periodDelivery引用,后续更新无法同步。
解决方案
方案1:确保触发Angular消化循环
在更新$scope变量后,手动触发$apply或用$timeout包裹,确保Angular感知到变量变化:
function getDaysClosedFromLocation(locationId) { LocationDaysService.getPeriodsDaysClosedFromLocation( locationId, function (response) { if (response.success) { // 用$timeout确保触发digest循环 $timeout(function() { $scope.periodDelivery = response.data; $scope.periodReturn = response.data; initDatePickers(); }); } }, ); }
方案2:正确销毁并重建Datepicker
避免重复初始化,先销毁已有实例再重建,同时直接在配置中使用匿名函数获取最新$scope值:
function initDatePickers() { // 先销毁已有的datepicker实例 $("#date_entrega").datepicker('destroy'); $("#date_devolucion").datepicker('destroy'); $("#date_entrega") .datepicker({ language: "es", format: "dd/mm/yyyy", autoclose: true, todayHighlight: true, orientation: "left", beforeShowDay: function(date) { // 直接使用最新的$scope.periodDelivery,避免闭包问题 return beforeShowDay(date, $scope.periodDelivery); }, }) .on("changeDate", function (ev) { $scope.configuracionCambioFechaHora("date_entrega"); // 触发digest确保ng-model同步 $scope.$apply(); }); $("#date_devolucion") .datepicker({ language: "es", format: "dd/mm/yyyy", autoclose: true, todayHighlight: true, orientation: "left", beforeShowDay: function(date) { return beforeShowDay(date, $scope.periodReturn); }, }) .on("changeDate", function (ev) { $scope.configuracionCambioFechaHora("date_devolucion"); $scope.$apply(); }); }
方案3:优化beforeShowDay逻辑
移除中间包装函数,直接在datepicker配置中使用匿名函数,确保每次调用都获取最新的$scope变量:
// 移除beforeShowDayDatePickerDelivery和beforeShowDayDatePickerReturn函数 // 在datepicker配置中替换为: beforeShowDay: function(date) { return beforeShowDay(date, $scope.periodDelivery); }
额外提示
- 尽量避免在AngularJS中直接操作DOM(如
$("#date_entrega")),推荐使用AngularJS生态的datepicker指令(如ui-bootstrap的datepicker),能更好地与Angular的生命周期同步。 - 如果必须使用jQuery的datepicker,确保所有DOM操作和
$scope更新都在Angular的消化循环内完成。
内容的提问来源于stack exchange,提问作者Zenin0
相关产品推荐
相关产品推荐

