You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

切换地点后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方法、判断是否已创建等方案,均无效。

原因分析

  1. AngularJS消化循环未触发:LocationDaysService的回调属于异步操作,更新$scope.periodDelivery后,Angular可能未及时触发$digest循环,导致beforeShowDayDatePickerDelivery函数捕获的还是旧的$scope.periodDelivery值。
  2. 重复初始化冲突:每次切换地点都重新调用datepicker()初始化,可能导致#date_entrega的datepicker实例存在多个配置,旧的beforeShowDay逻辑未被覆盖。
  3. 闭包捕获旧值: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 03:37:03