为什么我的组件绑定在其控制器中未定义?

时间:2016-07-26 13:47:17

标签: javascript angularjs angularjs-1.5

我正在写一个简单的角度组件。我将参数作为绑定传递并在屏幕上显示其值。一切正常:我可以看到屏幕上显示的参数。

组件:

var app = angular.module("test", []);
app.component("test", {
  bindings: {
    "contactId": "<"
  },
  controllerAs: "model",
  controller: () => {
    //output: 'contact id from controller: undefined'
    console.log(`contact id from controller: ${this.contactId}`);
  },
  template: "<div>Contact id from view: {{model.contactId}}</div>"
});

HTML:

<test contact-id="8"></test>

但是,当我尝试从控制器中访问绑定时(请参阅console.log),绑定值为undefined。我不明白它在视图中是如何可用的,而不是在控制器中。

我做错了什么?

这是一个说明问题的plnkr

9 个答案:

答案 0 :(得分:51)

使用角度组件时,控制器尚未通过内部链接进行连接。如果您尝试在控制器的构造函数中执行此操作,则表示您尚未将链接绑定到绑定。 Component API公开了一些你可以定义的生命周期钩子,它会在特定时间触发。您正在寻找$onInit挂钩。

  

$ onInit() - 在构造了元素上的所有控制器并初始化其绑定之后(在此元素上的指令的pre&amp; post链接函数之前),在每个控制器上调用。这是为控制器放置初始化代码的好地方。

每个文档 - https://docs.angularjs.org/guide/component

答案 1 :(得分:20)

确保在HTML和camelCase中使用连字符进行绑定,以便在Javascript中进行绑定。

app.component("test", {
  bindings: {
    "myContactId": "<"
  }
}

<test my-contact-id="8"></test>

这就是我一直忘记做的事情。

答案 2 :(得分:7)

(Get-Content my.json) -replace '(?<pre>"version"[\s]*:[\s]*)(?<V>"[^\"]*")', '$1"$version"' | Out-File my.json 的值可在控制器的contactId上找到:

$scope

链接到另一个版本的Plunker here

答案 3 :(得分:6)

关键字似乎不适用于箭头功能,这适用于

controller: function() {
   alert('contact id from controller: ' + this.contactId);
}

使用箭头功能时,这个,似乎是指窗口对象,因为

  

箭头函数不会创建它自己的上下文,而是它   捕获封闭上下文的这个值

答案 4 :(得分:4)

我会建议你做一些改变,以避免这些不寻常的错误。

app.component("test", {
  bindings: {
    "myContactId": "<"
  },
  controller:function(){
   var self=this;
   this.$onInit=function(){
    // do all your initializations here.
    // create a local scope object for this component only. always update that scope with bindings. and use that in views also.

       self.myScopeObject=self.myContactId
   }
  },
   template:'<p>{{$ctrl.myScopeObject}}</p>'
 }

<test my-contact-id="8"></test>

一些观点:

  1. 将绑定传递给html中的组件始终是kebab cased ex my-contact-id,其各自的javascript变量将是cammal cased:myContactId。

  2. 如果您传递了对象使用的值,请使用&#39; @&#39;在绑定中。 如果您正在使用对象并将对象传递给bindigs,请使用&#39;&lt;。 如果你想要对该对象进行双向绑定,请使用&#39; =&#39;在bindings config

  3.  bindings:{
          value:'@',
          object:'<', // also known as one-way
          twoWay:'='
        }
    

答案 5 :(得分:1)

它可能不是最佳做法,但您可以轻松访问这些值:

$scope.$ctrl.contactId

您可以在$ scope内的$ ctrl属性中获取所有绑定。

我希望得到它的帮助

答案 6 :(得分:0)

对于那些使用指令的人,如果指定了组件,如果指定了绑定{},则会将相同的参数添加到范围{}中:

/*bindings: {
    modalInstance: '<',
    resolve: '<'
},*/
scope: {
    modalInstance: '<',
    resolve: '<'
},

*在我写完上面的内容之后发现,在我从$ scope.resolve分配它之前,$ scope上没有另外的范围参数foo可用。所以我必须在$ scope.init()中执行此操作:$ scope.foo = $ scope.resolve.foo。不知道为什么。猜测它与我的UI Bootstrap Modal + Directives用法有关

对于其他人来说,这可能是显而易见的,但对于我来说,对于AnguluarJS来说,这并不是一个新手。

我的问题是使用带有UI-Bootstrap Modals的Directives,它与Directives兼容,但设计和记录用于组件。

答案 7 :(得分:0)

我将为@jusopi和接受的答案添加另一个答案,仅针对可能遇到我问题的人。关于组件,即使在经过$onInit钩之后,我的数据仍然为null,因为仍然没有收到来自服务器的值。为了解决这个问题(尽管可能有更好的方法来处理这种情况),我还利用了$onChanges钩子。 $onChanges将返回传递时已更改的数据,您可以解析该信息,或者简单地将绑定称为this.contactId并将其更新。

documentation中提供了更多详细信息:https://docs.angularjs.org/guide/component

答案 8 :(得分:0)

代码存在两个问题,导致“未定义”错误。

  1. 如上所述,应该首先到达$ onInit生命周期挂钩,在完成所有绑定后会触发onInit。

摘自官方文档:AngularJs Documentation

  

$ onInit()-在一个控制器上的所有控制器之后,在每个控制器上调用   元素已构造并已初始化其绑定(和   在此之前和之后链接功能的指令之前   元件)。这是放置初始化代码的好地方   控制器。

  1. 您可能遇到的第二个问题是,使用“()=>”箭头符号作为控制器功能的参数时,控制器将无法达到生命周期挂钩。

问题在于箭头表示法没有它自己的作用域,而是使用它的封闭作用域。 意味着使用“ this”时将引用窗口对象而不是组件。 因此调用this。$ onInit()将在窗口上调用,并且不会被触发,因为它在窗口上不存在。