AngularJS 1.4指令:范围,双向绑定和bindToController [英] AngularJS 1.4 directives: scope, two way binding and bindToController

查看:800
本文介绍了AngularJS 1.4指令:范围,双向绑定和bindToController的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


  

更新:这一定是什么东​​西在code的另一部分愚蠢。现在的工作,所以bindToController语法是好的。


我们正在使用AngularJS 1.4,它推出了新的方式来使用bindToController 的指令。

相当多的阅读(也许不理解的所有内容)后,我们定义了我们的指令是这样的:

  .directive('mdAddress',功能mdAddress(){
    var命令= {
      限制:EA,
      范围: {},
      bindToController:{
        地址:'='
      },
      templateUrl:'模块/地址/ address.html',
      控制器:AddressController,
      controllerAs:'目录'
    };

这样从另一种观点认为它调用

 < MD-地址地址=vm.address>< / MD-地址>

在视图控制器pviously定义有$ P $:

  vm.address = {
    街道:空,
    国家code:空,
    城市code:空,
    邮政code:空
  };

在引用该指令模板中的变量是这样的:

 < MD-输入容器>
    <标签> {{'ADDRESSNUMBER|翻译}}< /标签>
    <输入类型=数字NG-模式=dir.address.streetNumber>
  < / MD-输入容器>

我们花了4小时试图弄清楚为什么我们的指令,没有工作。嗯,这是工作,而是双向的控制器和指令之间结合得不行, vm.address.street 绝望地设置为null。

过了一会儿,我们只是尝试了旧的方式:

  .directive('mdAddress',功能mdAddress(){
    var命令= {
      限制:EA,
      范围: {
        地址:'='
      },
      bindToController:真实,
      templateUrl:'模块/地址/ address.html',
      控制器:AddressController,
      controllerAs:'目录'
    };

和它神奇的工作。任何想法的为什么


解决方案

更新:

感谢参考这篇博客,我需要更新我的回答。由于AngularJS 1.4它似乎真的,你可以使用

 范围:{},
bindToController:{
  变量:'='
}

这将做(精确)同样的事情,旧的语法:

 范围:{
  变量:'='
},
bindToController:真

从AngularJS源$ C ​​$ C有用的线条来解释这一行为:

 如果(则IsObject(directive.scope)){
  如果(directive.bindToController ===真){
    bindings.bindToController = parseIsolateBindings(directive.scope,
                                                     directiveName,真正的);
    bindings.isolateScope = {};
  }其他{
    bindings.isolateScope = parseIsolateBindings(directive.scope,
                                                 directiveName,FALSE);
  }
}
如果(则IsObject(directive.bindToController)){
  bindings.bindToController =
      parseIsolateBindings(directive.bindToController,directiveName,真正的);
}

来源: AngularJS 1.4.0

原来的答复:

希望我可以解释,为什么你这种行为,你经历的是正确的,在这里你做missunderstand范围的概念结合在那里。

让我解释一下,你在你的第一个code段所做的:

  .directive('mdAddress',功能mdAddress(){
    var命令= {
      限制:EA,
      范围: {},
      bindToController:{
        地址:'='
      },
      templateUrl:'模块/地址/ address.html',
      控制器:AddressController,
      controllerAs:'目录'
    };

使用范围:{} ,您创建了一个孤立的范围(没有任何继承)为你的 mdAddress 指令。这意味着:没有数据父控制器和您的指令之间传递

有了这个想法,关于你的第二个code片断:

 < MD-地址地址=vm.address>< / MD-地址>

vm.address 从父控制器/视图将被指定为前pression的指令的地址属性,但正如你之前定义的隔离范围,数据不会传递到 AddressController ,因此在 bindToController 价值不可用。

让我们觉得范围对象定义为数据将被传入和 bindToController 作为在哪些数据会在我的观点的controllerAs对象可用。

所以,现在让我们来看看最后一个(和工作code段):

  .directive('mdAddress',功能mdAddress(){
    var命令= {
      限制:EA,
      范围: {
        地址:'='
      },
      bindToController:真实,
      templateUrl:'模块/地址/ address.html',
      控制器:AddressController,
      controllerAs:'目录'
    };

有您创建一个孤立的范围了,但是这个时候你添加了地址属性中传递作为前pression。所以现在的地址您从第二个片段的观点传递将在控制器的范围内使用。设置 bindToController:真正的现在,将绑定到控制器的所有当前范围的属性(或者更可能的controllerAs对象)。而现在,它的工作原理正如你所期望的,因为数据将被传递到范围和数据将被传递到控制器的模板范围。

难道是简要介绍可以帮助您更好地理解范围的概念 bindToController 定义对象?

Update: It must have been something stupid in another part of the code. It works now, so the bindToController syntax is fine.

We are using AngularJS 1.4, which introduced a new way to use bindToController in directives.

After quite a bit of reading (and maybe not understanding everything), we defined our directive like this:

  .directive('mdAddress', function mdAddress() {
    var directive = {
      restrict: 'EA',
      scope: {},
      bindToController: {
        address: '='
      },
      templateUrl: 'modules/address/address.html',
      controller: AddressController,
      controllerAs: 'dir'
    };

Calling it from another view like this:

  <md-address address="vm.address"></md-address>

Having previously defined in the view controller:

  vm.address = {
    street: null,
    countryCode: null,
    cityCode: null,
    postalCode: null
  };

Referencing the variables in the directive template like this:

  <md-input-container>
    <label>{{'ADDRESSNUMBER' | translate}}</label>
    <input type="number" ng-model="dir.address.streetNumber">
  </md-input-container>

We spent 4h trying to figure out why our directive was not working. Well, it was working, but the two-way binding between the controller and the directive was not, vm.address.street was hopelessly set to null.

After a while, we just tried the old way:

  .directive('mdAddress', function mdAddress() {
    var directive = {
      restrict: 'EA',
      scope: {
        address: '='
      },
      bindToController: true,
      templateUrl: 'modules/address/address.html',
      controller: AddressController,
      controllerAs: 'dir'
    };

And it magically worked. Any idea WHY?

解决方案

Update:

Thanks to the reference to this blog post, I need to update my answer. Since AngularJS 1.4 it really seems, that you can use

scope: {},
bindToController: {
  variable: '='
}

which will do the (exact) same thing as the old syntax:

scope: {
  variable: '='
},
bindToController: true

The useful lines from the AngularJS source code to explain this behavior:

if (isObject(directive.scope)) {
  if (directive.bindToController === true) {
    bindings.bindToController = parseIsolateBindings(directive.scope,
                                                     directiveName, true);
    bindings.isolateScope = {};
  } else {
    bindings.isolateScope = parseIsolateBindings(directive.scope,
                                                 directiveName, false);
  }
}
if (isObject(directive.bindToController)) {
  bindings.bindToController =
      parseIsolateBindings(directive.bindToController, directiveName, true);
}

Source: AngularJS 1.4.0

Original answer:

Hopefully, I can explain you why this behavior you experienced is correct and where you did missunderstand the concept of scope binding there.

Let me explain, what you did in your first code snippet:

.directive('mdAddress', function mdAddress() {
    var directive = {
      restrict: 'EA',
      scope: {},
      bindToController: {
        address: '='
      },
      templateUrl: 'modules/address/address.html',
      controller: AddressController,
      controllerAs: 'dir'
    };

With scope: {}, you created an isolated scope (without any inheritance) for your mdAddress directive. That means: No data is passed between the parent controller and your directive.

Having this in mind, regarding your second code snippet:

<md-address address="vm.address"></md-address>

vm.address from your parent controller/view will be assigned as expression to the address attribute of the directive, but as you defined an isolated scope before, the data is not passed into AddressController and therefore not available in the bindToController value.

Let's think of the scope object definition as the "which data will be passed in" and the bindToController as the "which data will be available in my view's controllerAs object".

So, now let's have a look at the last (and working code snippet):

.directive('mdAddress', function mdAddress() {
    var directive = {
      restrict: 'EA',
      scope: {
        address: '='
      },
      bindToController: true,
      templateUrl: 'modules/address/address.html',
      controller: AddressController,
      controllerAs: 'dir'
    };

There you created an isolated scope, too, but this time you added the address attribute to be passed in as an expression. So now the address you passed in from the view in the second snippet will be available in the controller's scope. Setting bindToController: true now, will bind all the current scope's properties to the controller (or more likely the controllerAs object). And now, it works as you would expect, because data will be passed in to the scope and data will be passed out to the controller's template scope.

Did that brief overview help you to better understand the concept of the scope and bindToController definition objects?

这篇关于AngularJS 1.4指令:范围,双向绑定和bindToController的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆