【问题标题】:Angular directive: using ng-model within isolate scopeAngular 指令:在隔离范围内使用 ng-model
【发布时间】:2014-08-07 14:03:22
【问题描述】:

我无法确定如何定义一个自定义指令:

  1. 使用隔离范围,并且
  2. 在其模板的新范围内使用 ng-model 指令。

这是一个例子:

HTML:

<body ng-app="app">
  <div ng-controller="ctrl">
    <dir model="foo.bar"></dir>
    Outside directive: {{foo.bar}}
  </div>
</body>

JS:

var app = angular.module('app',[])
  .controller('ctrl', function($scope){
    $scope.foo = { bar: 'baz' };
  })
  .directive('dir', function(){
    return {
      restrict: 'E',
      scope: {
        model: '='
      },
      template: '<div ng-if="true"><input type="text" ng-model="model" /><br/></div>'
    }
  });

此处所需的行为是输入的值通过指令的(隔离)范围model 属性绑定到外部范围的foo.bar 属性。这不会发生,因为模板封闭 div 上的 ng-if 指令创建了一个新范围,因此更新的是该范围的 model,而不是指令的范围。 通常,您通过确保表达式中有一个点来解决这些 ng-model 问题,但我在这里看不到任何方法。我想知道我是否可以在我的指令中使用这样的东西:

{
  restrict: 'E',
  scope: {
    model: {
      value: '=model'
    }
  },
  template: '<div ng-if="true"><input type="text" ng-model="model.value" /><br/></div>'
}

但这不起作用......

Plunker

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-scope


    【解决方案1】:

    ng-if 创建了一个额外的原型继承作用域,因此ng-model="model" 绑定到新作用域的继承属性,而不是指令作用域的 2 路绑定属性。

    将其更改为ng-show,它将变为work

    您可以使用我写的a small Firebug extension 来检查角度范围。

    【讨论】:

    • 是的,我知道这就是正在发生的事情 - 我故意使用 ng-if 只是为了演示这个问题
    【解决方案2】:

    你是对的 - ng-if 创建了一个子范围,当在输入文本字段中输入文本时会导致问题。它在子作用域中创建了一个名为“模型”的影子属性,该属性是具有相同名称的父作用域变量的副本——有效地破坏了双向模型绑定。

    解决这个问题很简单。在您的模板中,指定 $parent 前缀:

      template: '<div ng-if="true">
                       <input type="text" ng-model="$parent.model" /><br/>
                 </div>'
    

    这确保它将从 $parent 作用域解析“模型”,您已经为通过隔离作用域的双向模型绑定设置了该作用域。

    最后,'.'在 ng-model 中节省了一天。我发现将点的任何剩余部分视为 Angular 通过范围继承解析属性的一种方式很有用。如果没有点,解析属性只会在我们分配范围变量时成为问题(否则,查找很好,包括只读的{{model}} 绑定表达式)。

    【讨论】:

    • 谢谢 - 我完全忘记了 $parent。在这种情况下,这确实解决了我的问题,但我仍然对它作为通用解决方案有点犹豫:这意味着我必须跟踪在我的模板中引入新范围的位置以及我需要的层次结构级别目标,这似乎很容易出错......
    • 我同意你的看法。 Misko 解释说,有人大约每周记录一次关于此的错误 - 这并不是真正的错误,它是原型继承的工作方式。要正确设置 ng-model,您需要更深入地了解作用域继承的工作原理,以及哪些指令将创建子作用域。不过我想不出更好的方法。
    • 是的,公平点,虽然我想我得到的是使用 ng-model="$parent.bar" 而不是 ng-model="foo.bar ",对于前者,我总是必须考虑在哪里创建子作用域,而对于后者,我不需要(只要我可以假设没有子作用域具有名为 'foo' 的属性)。跨度>
    • 回复。更新:感谢您的建议,但我认为这不起作用 - 使用此方法更改输入值时会更新 $scope.foo.bar,但 $scope.foo.bar 和模型属性之间没有双向绑定从外部控制器传递到指令中,因此外部属性不会更新。见plnkr.co/edit/1ZnUEbJHybq3765PxgoY?p=preview(我不得不稍微调整你的例子,但我认为它反映了你的想法)。
    • 在您的示例中,“foo”正在解析为不同的引用。酒吧是一个原始人。这就是打破双向绑定的原因。您应该将 foo 作为模型传递,所有这些问题都会消失。
    猜你喜欢
    • 2013-09-04
    • 2014-12-26
    • 1970-01-01
    • 2017-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-12
    • 2013-03-15
    相关资源
    最近更新 更多