2013-03-01 144 views
35

我想要訪問控制器功能中指令的屬性。但是,當我訪問它時,它是不確定的。我注意到,如果我做了一個簡單的計時器,它的作品。有沒有一種方法可以在指令之後執行代碼,並且它的作用域已準備好並設置爲使用?AngularJS指令屬性訪問控制器

我用它做了一個小提琴。確保您的控制檯處於打開狀態。 http://jsfiddle.net/paulocoelho/uKA2L/1/

這裏是我使用的小提琴代碼:

<div ng-app="testApp" > 
    <testcomponent text="hello!"></testcomponent> 
</div> 
var module = angular.module('testApp', []) 
    .directive('testcomponent', function() { 
    return { 
     restrict: 'E', 
     template: '<div><p>{{text}} This will run fine! </p></div>', 
     scope: { 
      text: '@text' 
     }, 
     controller: function ($scope, $element) { 
      console.log($scope.text); // this will return undefined 
      setTimeout(function() { 
       console.log($scope.text); // this will return the actual value... 
      }, 1000); 
     }, 
     link: function ($scope, $element, $attrs) { 
      console.log($scope.text); 
      setTimeout(function() { 
       console.log($scope.text); 
      }, 1000); 
     } 
    }; 
}); 

回答

25

什麼工作,如果你設置

scope.text = $attrs.text; 

鏈接和控制器功能裏面。這隻會在最初才起作用,因爲沒有二維數據綁定。不過,您可以使用$attrs.observe

見琴:http://jsfiddle.net/JohannesJo/nm3FL/2/

+0

燁,爲我工作:)感謝的人 – PCoelho 2013-03-01 06:06:52

+1

這將失敗掉毛。因爲'attrs.text'是未知的。 – 2016-10-24 12:36:38

+1

@DougChamberlain你可以使用JSDoc來解決這個問題。像''@param {string} attrs.text''應該可以解決你的問題。 – 2017-07-24 13:10:40

1

鏈接功能之前,$在那一刻範圍內的變量是不確定稱爲消化循環。查看this chapterthis other以瞭解鏈接功能的運行方式。您只使用鏈接功能來爲指令定義手錶和/或行爲,而不是操縱模型,這是在控制器中完成的。

+0

這並非全部如此。範圍變量由鏈接後功能運行的時間來定義,並且在鏈接函數中操作數據模型是很好的。如果您打算使用它來通過require屬性與另一個指令進行通信,則僅在指令上需要控制器。控制器實際上首先運行,然後是預鏈接,一直沿着dom樹走向樹葉,然後後鏈接回根目錄。請參閱此主題以獲得澄清。 https://stackoverflow.com/questions/24615103/angular-directives-when-and-how-to-use-compile-controller-pre-link-and-post – 2018-03-08 17:10:30

23

在分離的範圍,局部範圍的屬性與定義的「@」不能在連接功能來訪問。正如@remigio已經提到的那樣,這種局部範圍屬性在undefined。 $ attrs。$ observe()或$ scope。$ watch()必須用於異步獲取(插值)值。

如果您在屬性中傳遞了一個常數值(即不需要插值,即該屬性的值不包含任何{{}}),則不需要'@'或$ observer或$觀看。您可以使用$ attrs。 ATTRIBUTE_NAME一次作爲@hugo建議,或者如果你是傳遞一個數字或一個布爾值,並要得到正確的類型,你可以用$範圍。$的eval($ ATTRS。屬性名稱)一次。

如果您使用'='將本地範圍屬性數據綁定到父範圍屬性,則該屬性的值將在鏈接功能中可用(不需要$ observe或$ watch或$ eval)。

+0

+1這是我逼瘋。 – GFoley83 2013-04-24 09:08:32

+0

+1感謝您的解釋! – 2013-11-08 02:54:01

0

如果您正在訪問您的指令,這個值使用指令在視圖中插入你可以使用$編譯API和做這樣

var string = "<div> " + scope.text + "</div>"; 
$compile(string)(scope, function(cloned, scope){ 
     element.append(cloned); 
}); 
7

東西由於角1.3訪問這個屬性,你可以使用bindToController。以下是我如何使用它的示例。在這裏,我的屬性添加範圍,然後用bindToController使用該控制器內部:

var module = angular.module('testApp', []) 
    .directive('testcomponent', function() { 
    return { 
     restrict: 'E', 
     template: '<div><p>{{text}} This will run fine! </p></div>', 
     scope: { 
      text: '@text' 
     }, 
     controller: function() { 
      console.log(this.text); 
     }, 
     controllerAs: 'vm', 
     bindToController: true 
    }; 
}); 

角1.3引入了一個新的屬性稱爲bindToController指令定義 對象,這不正是它說。當 在使用controllerAs, 的隔離範圍的指令中設置爲true時,組件的屬性將綁定到控制器而不是 範圍。這意味着,角可以確保,當控制器 實例化,分離的範圍綁定的初始值是在此 可用的,及未來的變化也自動 可用。

+1

這不適合我,this.text是未定義的。 – rjh 2016-07-11 05:54:03

+0

@rjh當你調用像這樣的指令時,你傳遞了「文本」嗎? '' – Neel 2016-07-30 03:16:38

5

而不是使用$scope得到指令屬性值,我個人更喜歡使用$attrscontroller功能,或者只是attrslink函數的第三個參數。我沒有問題,當下面的代碼不會發生超時得到一個controller的屬性值:

var module = angular.module('testApp', []) 
    .directive('testcomponent', function() { 
    return { 
    restrict: 'E', 
    template: '<div><p>{{text}} This will run fine! </p></div>', 
    scope: { 
     text: '@text' 
    }, 
    controller: ['$scope','$attrs', function ($scope, $attrs) { 
     console.log($attrs.text); // just call to the $attrs instead $scope and i got the actual value 
     $scope.text = $attrs.text; //assign attribute to the scope 
    }] 
    }; 
});