2013-10-13 57 views
20

我試圖達到父「框」指令遞歸的控制器:如何通過遞歸地訪問父指令的控制器?

<body ng-app="main"> 

<!-- no nesting: parent is the just body --> 
<box></box> 

<script type="text/javascript"> 
angular.module('main', []) 
.directive('box', function() { 
    return { 
     restrict: 'E', 
     controller: function() { }, 
     require: '?^box', // find optional PARENT "box" directive 
     link: function(scope, iElement, iAttrs, controller) { 
      // controller should be undefined, as there is no parent box 
      alert('Controller found: ' + (controller !== undefined)); 
     } 
    }; 
}); 
</script> 
</body> 

我期望控制變量是在鏈接功能undefined,但我得到的實際箱指令的控制器。

所以我的問題是...如何獲得這樣的訪問父控制器的情況下:

<box> 
    <box></box> 
</box> 

http://jsfiddle.net/gjv9g/1/

回答

18

OK,找到了......

,如果你想獲得一個父元素的控制器的保持:

... 
link: function(scope, iElement, iAttrs, controller) { 
    // http://docs.angularjs.org/api/angular.element 
    // jQuery/jqLite Extras: 
    // 
    // controller(name) - retrieves the controller of the current element or its parent. 
    // By default retrieves controller associated with the ngController directive. 
    // If name is provided as camelCase directive name, then the controller for this 
    // directive will be retrieved (e.g. 'ngModel'). 
    var parentCtrl = iElement.parent().controller('box'); 
} 
... 

這將返回母指令或者控制器,或者一個級別越高,父親的父親指令的控制器,如果你需要確保你得到一個直接父的控制器,我發現這個(也許有更好的解決方案,我不知道):

... 
controller: function($scope, $element) { 
    // store the element in controller, we'll need it later 
    this.$element = $element; 
}, 
// works in both pre and post link functions 
link: function() { 
    var parentElement = $element.parent(); 
    var parentCtrl = parentElement.controller('box'); 

    var hasDirectBoxParent = parentCtrl && parentCtrl.$element[0] === parentElement[0]; 

} 
... 

實施例1:

<box id="a"> 
    <box id="b"></box> 
<box> 

當鏈路功能的「框」調用,parentCtrl是在兩種情況下undefined。 當在「box b」上調用鏈接函數時,parentCtrl在兩種情況下都是「box a」的控制器。

實施例2:

<box id="a"> 
    <div> 
     <box id="b"></box> 
    </div> 
<box> 

當鏈路功能的 「框」 調用,parentCtrl是在兩種情況下undefined。 當在「box b」上調用鏈接函數時,parentCtrl在這兩種情況下仍然是「box a」的控制器,但hasDirectBoxParent是false,因此您可以將祖父母與祖父母區分開來。

4

require從所需要的(父)指令注入控制器到電流指令(從角文檔:「需要 - 需要另一個指令,並注入其控制器作爲第四個參數邏輯函數」 http://docs.angularjs.org/guide/directive

因此,也許你已經getti你想要什麼?也就是說,通過參數controller將父控制器注入到孩子身上。

+0

取代require: '?^box',你可以看到,有我原來的例子沒有父框,所以我希望得到'undefined'作爲第四個參數的鏈接功能,而不是實例本身的控制器 – maX

+0

但是你聲明瞭一個控制器。所以父母得到那個控制器和孩子(如果有的話)繼承它。你的目標是要知道一個特定的指令是父母還是孩子?如果是這樣,也許你想看看$父範圍? – KayakDave

+1

其實我不想在這種情況下使用範圍,因爲範圍可能會變得棘手,特別是如果您需要使用隔離範圍。 另外,最好的做法是使用控制器和'require'進行指令到指令的通信。 我的觀點是,當你需要一個不同名字的父指令時,它就像一個魅力一樣,你爲什麼不能夠遞歸地做到這一點。 – maX

39

由於Angular 1.3可以使用兩種口音^^在父元素「only」中搜索指令。從Angular Docs on require

引用:

  • (no prefix) - 找到當前元素所要求的控制器。如果找不到,則拋出一個錯誤。
  • ? - 嘗試找到所需的控制器或將null傳遞給鏈接fn(如果未找到)。
  • ^ - 通過搜索元素及其家長找到 所需的控制器。如果找不到,則拋出一個錯誤。
  • ^^ - 通過搜索元素的父母找到所需的控制器。如果找不到,則拋出一個錯誤。
  • ?^ - 嘗試通過搜索元素及其家長找到所需要的控制器或傳遞null如果沒有找到FN的鏈接。
  • ?^^ - 嘗試通過搜索元素的父母找到所需要的控制器,或傳遞null FN的鏈接,如果沒有找到。

在你的情況下,require: '?^^box',