AngularJS控制器$scope变量赋值后重置问题求助
解决AngularJS中日期选择器修改后变量恢复初始值的问题
看起来你遇到了AngularJS里经典的作用域遮蔽问题,这在使用像uib-datepicker-popup这类会创建子作用域的指令时很常见。我来帮你拆解问题并给出解决方案:
问题原因
AngularJS的子作用域是基于原型继承的,当你直接把ng-model绑定到$scope的顶层属性(比如你的$scope.date)时,子作用域(比如日期选择器内部的作用域)会创建一个属于自己的属性副本,而不是修改父作用域的原始属性。这就导致:
- 你在
setDate里看似修改了$scope.simStartDate,但可能只是修改了子作用域的变量 - 当你点击按钮调用
ParamsFormBtnClicked时,读取的却是父作用域里未被修改的初始值
解决方案:使用"点语法"包裹变量
AngularJS开发的最佳实践之一是用一个对象来包裹所有表单相关的变量,这样就能避免作用域遮蔽。子作用域会通过原型链访问父作用域的对象,而不会创建新的副本。
修改后的控制器代码
angular.module('BlurAdmin.pages.dashboard') .controller('DashboardParamsFormCtrl', DashboardParamsFormCtrl); /** @ngInject */ function DashboardParamsFormCtrl(baConfig, layoutPaths, baUtil, $scope) { // 用form对象包裹所有表单变量,避免作用域问题 $scope.form = { simStartDate: new Date(), date: new Date() }; $scope.ParamsFormBtnClicked = function() { console.log("Date: " + $scope.form.simStartDate); }; $scope.open = open; $scope.opened = false; $scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate']; $scope.format = $scope.formats[0]; $scope.options = { showWeeks: false }; function open() { $scope.opened = true; } $scope.setDate = function(startDate) { $scope.form.simStartDate = startDate; }; } })();
修改后的HTML模板
<div class="row" ng-controller="DashboardParamsFormCtrl"> <div class="col-sm-6"> <div class="form-group"> <label for="inputFirstName">Simulation start date</label> <p class="input-group"> <input type="text" class="form-control" uib-datepicker-popup="{{format}}" datepicker-options="options" ng-model="form.date" ng-change="setDate(form.date)" is-open="opened" ng-required="true" close-text="Close" alt-input-formats="altInputFormats" show-button-bar="true" /> <span class="input-group-btn"> <button type="button" class="btn btn-default" ng-click="open()"> <i class="glyphicon glyphicon-calendar"></i> </button> </span> </p> </div> </div> <!-- 确保你的按钮也在同一个控制器作用域内 --> <button class="btn btn-primary" ng-click="ParamsFormBtnClicked()">Submit</button> </div>
为什么这样有效?
当你绑定到form.date时,子作用域会先查找自身的form属性,如果找不到,就会沿着原型链找到父作用域的form对象,然后直接修改它的date属性。这样setDate中更新的form.simStartDate就是父作用域中的同一个属性,按钮点击时自然能读取到正确的修改后的值。
另外,你可以检查一下页面上是否有多个元素使用了ng-controller="DashboardParamsFormCtrl",如果有的话也会导致控制器多次实例化,出现变量不一致的问题,但最可能的根源还是作用域遮蔽问题。
内容的提问来源于stack exchange,提问作者madu
相关产品推荐
相关产品推荐

