2016-07-26 84 views
36

我在写一个简单的角度组件。我传递一个参数作为绑定并在屏幕上显示它的值。所有工作正常:我可以看到屏幕上显示的参数。角度组件:绑定在控制器中未定义

组件:

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

+1

我失去了一些东西简单。为什么“contactId”用引号定义? – Winnemucca

回答

33

使用角度部件时,控制器没有通过连接的内部连线。如果你想在你的控制器的构造函数中这样做,你并不是链接到绑定。 Component API公开了一些生命周期钩子,您可以定义这些钩子将在特定时间触发。您正在寻找$onInit挂钩。

的OnInit $() - 已建成,并已裹脚布初始化(并在此元素的指令预&后链接功能之前)毕竟一个元素控制器每个控制器上调用。这是放置控制器初始化代码的好地方。

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

+1

我认为你是对的,应该使用'$ onInit'。这适用于我: ' var vm = this; vm。$ onInit = function(){ console.log('loaded on init'); console.log('vm',vm.YOUR_BINDING); console.log('def yes?',angular.isDefined(vm.YOUR_BINDINGj)); }; ' – escapedcat

+2

在某些情况下,您的绑定可以稍后更新,并且在钩子'$ onInit'被调用时,它的值没有准备好。在这种情况下,您应该使用'$ onChanges'并跳过第一次更改。工作示例:https://jsfiddle.net/auxcoder/4hq5gaq0/ – aUXcoder

+1

@aUXcoder这是我的问题。我试图在绑定到组件的数据准备好之前创建组件。放置一个'ng-if'指令以确保在组件初始化之前有数据(例如'')修复了这个问题。 – Xchai

4

似乎不带箭头的功能作品的关键字,这一点也适用

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

使用箭头功能,,似乎参照窗口对象,因为

箭头功能不会创建它自己的这种背景下,而是 抓住了封闭的上下文

6

contactId的值可在控制器的$scope的这个值:

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

链接到您的Plunker here的另一个版本。

+1

为什么我们在使用箭头函数样式时不能使用这个关键字? –

+0

您可以使用'this'与箭头函数样式,但我认为在这种情况下,'this.contactId'尚不可用,因为@jusopi提到的原因。如果你有API方法,比如someController.prototype.someMethod,这个''应该有你期望的。正如@jusopi提到的那样,执行顺序不会像预期的那样在构造函数(非原型)中填充“this”。 – JohnnyCoder

+1

我尝试了超时,它不起作用。正如我上面所说的,一个箭头函数不会创建它自己的这个上下文,而是它捕获封闭上下文的这个值。所以使用箭头函数,这是指窗口对象,而不是控制器。 –

13

请确保您使用连字符用于HTML中的绑定和用于Javascript中的绑定的camelCase。

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

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

这就是我经常忘记的事情。

1

它也许它不是最好的做法,但你有一个easyer访问这些值:

$scope.$ctrl.contactId 

你可以在$范围内的财产$ CTRL所有绑定。

我希望它的帮助

3

我会建议一些变化,你真的需要避免这些不寻常的错误。

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总是会被烤肉套管前我接触-ID及其相应的JavaScript变量将是cammal套管:myContactId。

  2. 如果您在绑定中传递对象使用'@'的insted值。 如果您使用的是对象并将对象传递给bindigs,则使用'<。 如果你想2路绑定在绑定该对象使用“=”配置

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