2016-07-26 116 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:'=' 
    }