2016-07-18 56 views
1

我創建了一個自定義指令,它顯示了一個列表和選擇框。爲什麼Angular自定義指令作用域會影響父控制器作用域?

請按照下面的代碼,

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <title>Template</title> 

    <script type="text/javascript" src="/home/rahul/Installers/jquery-3.0.0.js"></script> 
    <link rel="stylesheet" type="text/css" href="/home/rahul/Installers/Bootstrapv3.0.2/css/bootstrap.css"> 
    <link rel="stylesheet" type="text/css" href="/home/rahul/Installers/Bootstrapv3.0.2/css/bootstrap-theme.css"> 
    <script type="text/javascript" src="/home/rahul/Installers/Bootstrapv3.0.2/js/bootstrap.js"></script> 
    <script type="text/javascript" src="/home/rahul/Installers/angular.js"></script> 

    <script type="text/javascript"> 
     angular.module("app",[]); 
     angular.module("app").controller("myctrl",myctrl); 
     angular.module("app").controller("childCtrl",childCtrl); 
     angular.module("app").directive("loadFilms",loadFilms); 

     myctrl.$inject = ["$scope"]; 
     childCtrl.$inject = ["$scope"]; 

     function myctrl($scope){ 
      var vm = this; 
      vm.title = "Directive and nested scoping"; 
      vm.actorName = "Amithabh Bachhan"; 
      $scope.year = ["70's","80's","90's"]; 
     } 

     function childCtrl($scope){ 
      var vm = this; 

      vm.selectedYear = ""; 

      vm.moviesObj = { 
       "70's" : ["Anand","Lawaris","Kala Pathhar","Deewar","Amar Akbar Anthony","Mili"], 
       "80's" : ["Sharabi","Kaalia","Silsila","Satte Pe Satta","Nastik","Shahensha"], 
       "90's" : ["Hum","Aaj Ka Arjun", "Ajooba","Khuda Gawah","Ganga Jamuna Saraswati","Lal Badshah"] 
      } 

      vm.movies = []; 

      vm.getMovies = function(){ 
       vm.movies = vm.moviesObj[vm.selectedYear]; 
      } 
     } 

     function loadFilms(){ 
      return { 
       restrict : "EA", 
       controller : "childCtrl", 
       controllerAs : "vm", 
       scope : true, 
       template : function(tElem, tAttrs){ 
        var str = "<select ng-model='vm.selectedYear' data-ng-options='y as y for y in year' " + "class='form-control' ng-change='vm.getMovies()'>" + 
        "<option value=''>Select</option>" + 
        "</select>" + 
        "<br />" + 
        "<ol class='slide-animate-container'>" + 
        " <li class='slide-animate' ng-repeat='m in vm.movies'>{{m}}</li>"+ 
        "</ol>"; 
        return str; 
       } 
      } 
     } 
    </script> 
</head> 
<body> 
    <div ng-app="app" ng-controller="myctrl as vm" class="container"> 
     <div class="page-header"> 
      <h3>{{vm.title}}</h3> 
     </div> 
     <div class="row"> 
      <div class="col-md-6"> 
       <div class="page-header"> 
        <h5>{{vm.actorName}}</h5>      
       </div>      
      </div> 
     </div> 
     <div class="row"> 
      <div class="col-md-6" load-films></div> 
     </div> 
    </div> 
</body>  

的指令「加載影片」都有自己的適用範圍,

在該指令中的值來選擇框從傳遞封閉控制器「myctrl」中的父範圍變量。

工作例子是在鏈路現在 Example One

,一旦予改變指令「負載的膜」的範圍,以false

function loadFilms(){ 
      return { 
       restrict : "EA", 
       controller : "childCtrl", 
       controllerAs : "vm", 
       scope : false, 
       template : function(tElem, tAttrs){ 
        var str = "<select ng-model='vm.selectedYear' data-ng-options='y as y for y in year' " + "class='form-control' ng-change='vm.getMovies()'>" + 
        "<option value=''>Select</option>" + 
        "</select>" + 
        "<br />" + 
        "<ol class='slide-animate-container'>" + 
        " <li class='slide-animate' ng-repeat='m in vm.movies'>{{m}}</li>"+ 
        "</ol>"; 
        return str; 
       } 
      } 
     } 

vm.title和父控制器的vm.actorName不在UI中加載。

爲什麼?

理想vm.titlevm.actorName是在控制器「myCtrl」,那麼如何scope屬性設置爲指令false影響父控制變量,作爲 變量actorNametitle連接到this$scope

使用{.., scope = false,..}工作的例子是here

+0

將範圍:false更改爲範圍:{} –

回答

0

長答案:答案在於名稱轉換和初始化查詢。 如果調試什麼是初始化你將檢測:

  1. 首先是myctrl;
  2. 其次是childCtrl

如果您使用的應用scope: true下一個步驟:

  1. myctrl創建$scope和分配$scope.vm = myctrlmyctrl as vm);
  2. 創建$scopechildCtrl和轉讓$scope.vm = childCtrlcontrollerAs: mv);
  3. vm.titlevm.actorName取自第一步的$scope.vm

    1. myctrl創建$scope和分配$scope.vm = myctrlmyctrl as vm):

    如果scope: false會發生什麼

  4. 使用已創建$scopemyctrl其中$scope.vm已存在;
  5. 初始化指令時 - 用childCtrlcontrollerAs: 'vm')重寫$scope.vm;
  6. vm.titlevm.actorName取自第3步的$scope.vm(從childCtrl取代myctrl)。

簡短的回答: 每個控制器的初始化後,你還記得控制器的關係$scope.vm$scope.vm你有childCtrl代替myctrl,因爲它指示初始化過程中覆蓋和$scope是共享的。並且vm.titlevm.actorName不屬於childCtrl

4

你兩個controllerAs使用相同的名稱(vm)。因此變量被覆蓋。

0

擺脫您的指令中的控制器A和範圍。

controllerAs因爲它是強迫vm。在您的視圖中是您的指令的控制器上的屬性的別名,而不是您的外部視圖中定義的別名,並且範圍因爲您將它設置爲false時不需要它。

但是,即使這可以解決它,它不是理想的方法。理想情況下,你應該讓你的controllerAs,並有範圍看起來像這樣

scope : { 
    title : "@" 
} 

,然後改變你使用傳入的標題從

<blah load-films title="vm.title"/> 

Directives with isolated scope是更好的方式去查看,所以堅持controllerAs作用域但確保您想要在父級上的值通過參數顯式傳遞 - 這樣你不用不需要依賴包含您的指令的視圖來設置具有像「vm」這樣的特定別名的視圖(魔法字符串很糟糕)

相關問題