【问题标题】:AngularJS: changing $rootScope variable doesn't change first selected option in ng-modelAngularJS:更改 $rootScope 变量不会更改 ng-model 中的第一个选定选项
【发布时间】:2017-08-01 20:32:23
【问题描述】:

我有一个我似乎无法解决的特定问题。

在 html 中我有以下代码:

<select ng-model="$parent.proizvod"  ng-options="i.id_proizvod as i.proizvod for i in proizvodiServer">
   <option>Select</option>
 </select>

在我的控制器中:

  $rootScope.proizvod = '1';

所以当页面第一次加载时,第一个选项被选中。如果我将$rootScope.proizvod = '1'; 更改为$rootScope.proizvod = '3'; 它将加载第三个选项。

现在,当您选择其他值时,它会将其存储在 $rootScope.proizvod 中,但稍后,在某些功能中,我想将 $rootScope.proizvod 重置为“1”,但它似乎不起作用.

我在这里错过了什么?

附:如果没有$parent.proizvod,我的选择甚至不会更改$rootScope.proizvod 的值。

编辑:这是另一个功能:

$rootScope.upisPodataka = function() {
      setTimeout(function () {
      $rootScope.proizvod = '1';
      $scope.$apply();
       }, 2000);
      $state.go('app.podesenost_grilla', {}, {
        reload: true
      });

upisPodataka 函数在点击按钮时被调用。

【问题讨论】:

  • 显示你的“其他功能”
  • 和控制器里面的基本一样。我现在已经编辑了问题。
  • 为什么要使用 rootscope 来跟踪选择选项?所有范围都将继承该值..那是糟糕的设计。而是将值附加到控制器的范围。此外,使用 $setTimeout 而不是使用 setTimeout 并手动触发摘要循环。 $setTimeout 将在 $apply 中为您处理这些问题。
  • 我使用 $rootScope 是因为我在 2 个控制器中使用了该变量。
  • @MarcusH 封装 window.setTimeout 的 Angular 服务是 $timeout,见AngularJS $timeout API Reference

标签: javascript angularjs angularjs-rootscope javascript-inheritance


【解决方案1】:

使用ng-model='$parent.proizvod' 不能保证在所有情况下都能更新$rootScope

新的 AngularJS 开发人员通常没有意识到 ng-repeatng-switchng-viewng-includeng-if 都创建了新的子作用域,因此当涉及到这些指令时,问题通常会出现。

——AngularJS Wiki - Understanding Scopes

如果ng-model 在子范围内设置值。子作用域拥有自己的属性,该属性隐藏/隐藏同名的父属性。这不是 AngularJS 正在做的事情——这就是 JavaScript 原型继承的工作方式。阅读维基。

所以问题变成了应该是$parent.$parent.proizvod 吗?或者$parent.$parent.$parent.proizvod?通过反复试验来实现吗?

更稳健的方法是使用ng-change directive 来更新变量。

<select ng-model="vm.proizvod" ng-change="vm.update()"
        ng-options="i.id_proizvod as i.proizvod for i in proizvodiServer">
   <option>Select</option>
</select>
vm.update = function () {
    $rootScope.proizvod = vm.proizvod;
    console.log($rootScope.proizvod);
});

考虑使用custom service 来存储变量,而不是使用$rootScope

$rootScope存在,但可以作恶

AngularJS 中的作用域形成一个层次结构,原型继承自树顶部的根作用域。通常这可以忽略,因为大多数视图都有自己的控制器,因此也有自己的作用域。

有时,您想让某些数据对整个应用程序具有全局性。对于这些,您可以注入 $rootScope 并像任何其他范围一样在其上设置值。由于作用域从根作用域继承,这些值将可用于附加到指令的表达式,如 ng-show,就像本地 $scope 上的值一样。

当然,全局状态很糟糕,您应该谨慎使用$rootScope,就像(希望)在任何语言中使用全局变量一样。特别是,不要将其用于代码,仅用于数据。如果您想在 $rootScope 上放置一个函数,最好将它放在一个可以在需要的地方注入并且更容易测试的服务中。

相反,不要创建一个生活中唯一目的是存储和返回数据位的服务。

— AngularJS FAQ


使用 $timeout 代替 window.setTimeout

$rootScope.upisPodataka = function() {
      //setTimeout(function () {
      $timeout(function () {
         $rootScope.proizvod = '1';
         //$scope.$apply();
      }, 2000);
      $state.go('app.podesenost_grilla', {}, {
        reload: true
      });
};

$timeout service 包装 windows.setTimeout 并将其与 AngularJS 框架及其摘要循环集成。那么$apply()就不需要了。

另外,测试时可以使用$timeout.flush()

【讨论】:

  • 似乎完美无缺!不过有一件事,我知道子范围,所以这就是我把 $parent 放在上面的原因,但似乎我还没有完全掌握角度范围!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-05
  • 2021-03-19
  • 2022-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多