【问题标题】:ng-model not being updated outside of the scopeng-model 没有在范围之外更新
【发布时间】:2016-07-16 03:15:33
【问题描述】:

我将ng-model 绑定到输入,但它绑定的变量的值没有在声明该指令的div 之外更新:

<div input-field
     ng-if="startTypes.selected.value == 'LocalDate' || startTypes.selected.value == 'LocalDateTime'">
  <input id="date" type="text" ng-model="date" input-date>
  <label for="date">Date</label>
  Date inner scope: {{date}}
</div>
Date outer scope: {{date}}

选择新日期时,仅更新内部date。外面的值保留旧值(可能是 undefined 或不是,取决于我是否在控制器中声明它,没关系)。

我正在使用angular-materialize,我不确定这是否是问题的根源,但这没有意义,因为它是 Angular 与 CSS 框架 materializecss 一起使用的特定框架。

This 是我正在使用的组件。

编辑:

我尝试在控制器中将date 声明为$scope.date = new Date(),并且确实将当前日期加载到日期选择器中。 However when a date is selected and the model changes, it's only updated locally (inner scope), while in the outer scope the old value remains.

【问题讨论】:

  • 请同时发布您的控制器,或至少发布相关的 sn-p。
  • 不相关。我没有碰$scope.date。它甚至没有定义。我已经尝试定义它,其值为new Date(),并且所选日期中的初始日期确实是指定日期,但是在更新它时,仅更新内部范围,而不是来自控制器的$scope.date。

标签: javascript angularjs


【解决方案1】:

由于ng-if 创建了一个子范围,该子范围在将内部模板插入到 DOM 时原型从其当前范围继承,因此在这种情况下,ng-model 在ng-if 的子范围内创建。所以发生的事情是在创建child scope 时,它将primitive 数据类型值和reference(object) 数据类型值带到子范围,这就是为什么你可以看到外部范围date 在ng-if 日期内获取值字段(仅第一次)。但是当您更新date 中的值时,您不会看到该值更新到外部范围。因为child scope 的方式创建primitive type 值不携带它们的引用,而对象携带它们的引用。因此,您可以创建一个像$scope.model = {} 这样的对象,然后在其中定义一个属性,这样就可以了。因为对象带有对子范围的引用,所以更新内部对象也会同步外部对象(它们都是相同的)。此规则称为Dot Rule,您可以通过它解决您的问题。

$scope.model = {};
$scope.model.date = new Date();

避免这种范围层次结构的更方便的方法是在 HTML 上使用控制器时使用controllerAs 模式。在这种情况下,您不应该使用$scope,而是将所有属性绑定到控制器函数上下文(this)。此后在使用控制器时,您可以使用控制器的alias 来获取控制器的值,例如ng-controller="myCtrl as vm"(这里vm 是控制器的别名,所有信息都绑定到this)

HTML

<div input-field
     ng-if="vm.startTypes.selected.value == 'LocalDate' || vm.startTypes.selected.value == 'LocalDateTime'">
  <input id="date" type="text" ng-model="vm.date" input-date>
  <label for="date">Date</label>
  Date inner scope: {{vm.date}}
</div>
Date outer scope: {{vm.date}}

【讨论】:

  • 使用ng-show(它不会创建自己的范围)也可以解决问题,对吧?
  • @developer033 不是解决问题的正确方法,我会说Dot Rule/controllerAs
  • @developer033 看到它不能解决问题,它应该是适当的方式,就像你说的,$parent.date 也可以解决 OP 问题.. 但人们知道这是不好的模式,这就是为什么没有人也建议..
  • 不,我没说用$parent.date,我说直接把ng-if改成ng-show,用ng-show是不是不好?
  • 很好的解释! @PankajParkar
【解决方案2】:

绑定到ngModel时,您应该使用具有属性的对象。

$scope.form = {
   date: new Date()
};

【讨论】:

  • 我已经多次使用普通对象并且绑定非常完美。无论如何,form 是从哪里来的?
  • 这是你想要的。
  • 到底有什么用。你能解释一下为什么吗?我之前使用过ng-model 没有属性,我没有遇到任何问题。现在“失败”的原因是什么?
【解决方案3】:

ngIf like ngRepeat 指令创建自己的$scope。

因此,在这种特定情况下,您可以使用ng-show 而不是ng-if。

来自docs:

ngIf 指令删除或重新创建 DOM 树的一部分 基于一个{表达式}。如果分配给 ngIf 的表达式计算 为 false 值,则从 DOM 中删除该元素,否则为 元素的克隆被重新插入到 DOM 中。

示例:

angular.module('app', [])
  .controller('mainCtrl', function($scope) {
    $scope.testa = false;
    $scope.testb = false;
    $scope.testc = false;
    $scope.testd = false;
  });
<!DOCTYPE html>
<html ng-app="app">

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
</head>

<body ng-controller="mainCtrl">
  Test A: {{testa}}
  <br /> Test B: {{testb}}
  <br /> Test C: {{testc}}
  <br /> Test D: {{testd}}
  <br />

  <div>
    testa (without ng-if):
    <input type="checkbox" ng-model="testa" />
  </div>
  <div ng-if="!testa">
    testb (with ng-if):
    <!-- if you don't use $parent testb isn't updated -->
    <input type="checkbox" ng-model="$parent.testb" />
  </div>
  <div ng-show="!testa">
    testc (with ng-show):
    <input type="checkbox" ng-model="testc" />
  </div>
  <div ng-hide="testa">
    testd (with ng-hide):
    <input type="checkbox" ng-model="testd" />
  </div>
</body>

</html>

【讨论】:

  • 为什么会有帮助?无论如何,我只是按照您的建议尝试更改,但没有效果。
  • ngIf 创建自己的 $scope 作为 ngRepeat。
  • 好的,我明白了。但是正如我所说,我将ng-if 更改为ng-show,问题仍然存在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-22
  • 1970-01-01
  • 1970-01-01
  • 2016-11-19
  • 1970-01-01
相关资源
最近更新 更多