使用ng-model-options(UTC时区)时,打开bootbox模态框致ng-model值清空
这个问题我之前碰到过,核心原因是Bootbox的回调函数运行在AngularJS的上下文之外,再加上ng-model-options="{timezone: 'utc'}"的时区转换逻辑,在Angular的脏检查过程中导致日期模型意外清空。下面是具体的分析和解决方案:
问题根源
Bootbox是基于原生JavaScript的模态框库,它的回调函数不会自动触发AngularJS的消化循环(digest cycle)。当你在回调里访问vm.user时,Angular的脏检查机制会被动触发,而带有UTC时区配置的日期模型在这个过程中可能因为时区解析不一致,被转换成无效值甚至null——哪怕你没主动修改日期字段。
解决方案
1. 把Bootbox回调包裹在Angular上下文里
用$timeout或者$scope.$apply()把回调内的代码包裹起来,确保所有操作都在Angular的消化循环中执行,避免模型状态异常:
bootbox.confirm("Are you sure want to delete Test?", function (result) { // 用$timeout将回调逻辑纳入Angular上下文 $timeout(function() { console.log(vm.user); if (!result) { return; } let data = Object.assign({}, vm.user); data.exposureId = vm.user1._id; data.amount = (data.amount + "").split(',').join(''); UserService.DeleteTest(data).then(response => { console.log(response); vm.message = response.message; vm.show = true; $scope.isChecked = false; $timeout(function () { $scope.isChecked = true; }, 4000); }); }); });
2. 确保日期初始化是有效的Date对象
你的ng-init直接赋值vm.user.creationDate = vm.user1.creationDate,如果vm.user1.creationDate是字符串而非Date对象,Angular在UTC时区解析时很容易出错。建议在控制器里显式转换:
// 替换ng-init,在控制器初始化时处理 vm.user.creationDate = new Date(vm.user1.creationDate);
3. 优化时区与日期组件的兼容性
如果上述方法还不能解决,可以尝试移除输入框上的ng-model-options="{timezone: 'utc'}",转而在控制器层面统一处理UTC日期:
- 确保所有日期存储和传递都用UTC格式的Date对象
- 显示时用
date过滤器指定UTC时区,比如你已经在placeholder里做的那样
修改后的输入框代码:
<input type="text" name="creationDate" class="form-control req" uib-datepicker-popup="{{format}}" is-open="popup2.open" datepicker-options="dateOptions1" placeholder="{{vm.user.creationDate | date:'dd/MM/yyyy' : 'UTC'}}" ng-model="vm.user.creationDate" ng-change="vm.maturity(vm.user.creationDate, 'creationDate')" close-text="Close" alt-input-formats="altInputFormats" readonly="readonly" required />
验证方法
修改后可以在Bootbox回调的开头打印vm.user.creationDate,看看是否还会被清空。如果问题解决,说明是上下文和时区解析的冲突导致的。
内容的提问来源于stack exchange,提问作者Akshay

