2016-11-29 115 views
1

指令AngularJS - 從控制器調用特定的指令功能/法

myApp.directive('vlcControls', function ($compile, $rootScope, $timeout, $window, pictureboxConstants) { 


    var linker = function (scope, element, attrs) { 


    vlcPlayerCustomTemplate = 'some html goes here'; 


       scope.getVLC = function (name) { 
        if ($window.document[name]) { 
         return $window.document[name]; 
        } 
        if ($window.navigator.appName.indexOf("Microsoft Internet") == -1) { 
         if ($window.document.embeds && $window.document.embeds[name]) 
          return $window.document.embeds[name]; 
        } else { 
         return $window.document.getElementById(name); 
        } 
       } 

       scope.doPlayPause = function (vlcPlayer, event) { 
        var vlc = scope.getVLC(vlcPlayer); 
        if (vlc) { 

         if (vlc.playlist.isPlaying) { 
          vlc.playlist.pause(); 
          angular.element(event.target).children().removeClass('fa fa-pause font-12'); 
          angular.element(event.target).children().addClass('fa fa-play font-12'); 

         } else { 
          if (vlc.audio.mute == true) { 
           //do something 
          } 
          vlc.playlist.play(); 
         } 
        } 
       } 

      angular.element(document.querySelector("#controls" + index)).append(element.html(vlcPlayerCustomTemplate)); 
      $compile(element.contents())(scope); 
    }; 
    return { 
     restrict: "E", 
     link: linker 
    }; 
}); 

控制器

myModule.controller('myModuleCtrl', function ($scope, $http, $controller, $compile) { 

$compile("<vlc-controls></vlc-controls>")($rootScope); 

}); 

什麼是唯一的最佳方式調用特定的directive函數/方法doPlayPausecontroller無使用vlcPlayerCustomTemplate html元素或任何DOM操縱?

+0

只是我想知道,你有機會看看我的回答下面這很好地工作像''compile'一樣,沒有'DOM'操作? – Aruna

回答

1

您應該使用$broadcast$on來處理從控制器到指令的通信。

對我來說,這是一種代碼味道。如果父項和指令範圍之間共享某些內容,則應通過綁定完成。如果你必須像這樣使用pub-sub模式,你應該重新思考你如何使用你的指令,IMO。

您的指令應該能夠做任何需要的操作,而不需要直接從父控制器中調用。如果父控制器需要某些東西,則應該使用屬性或非隔離範圍來綁定它。

0

單程就是$broadcastcontrollerdirective的一個事件,並且聽取指令。

你甚至可以通過它發送對象形式的參數。

$rootScope.$broadcast('PlayPause',{});將在控制器

在指令

scope.$on('PlayPause',function(event, data){ 
     scope.doPlayPause(data.vlcPlayer, data.event) 
}); 

控制器:

myApp.controller('MyCtrl', function($rootScope){ 
    var that = this; 

    this.select = function(){ 
     $rootScope.$broadcast('PlayPause',{vlcPlayer: 'vlcPlayer',event: 'event'}); 
    } 
}) 

指令:

myApp.directive('vlcControls', function ($compile, $rootScope, $timeout, $window, pictureboxConstants) { 


    var linker = function (scope, element, attrs) { 


       scope.getVLC = function (name) { 
        if ($window.document[name]) { 
         return $window.document[name]; 
        } 
        if ($window.navigator.appName.indexOf("Microsoft Internet") == -1) { 
         if ($window.document.embeds && $window.document.embeds[name]) 
          return $window.document.embeds[name]; 
        } else { 
         return $window.document.getElementById(name); 
        } 
       } 

       scope.doPlayPause = function (vlcPlayer, event) { 
        var vlc = scope.getVLC(vlcPlayer); 
        if (vlc) { 

         if (vlc.playlist.isPlaying) { 
          vlc.playlist.pause(); 
          angular.element(event.target).children().removeClass('fa fa-pause font-12'); 
          angular.element(event.target).children().addClass('fa fa-play font-12'); 

         } else { 
          if (vlc.audio.mute == true) { 
           //do something 
          } 
          vlc.playlist.play(); 
         } 
        } 
       } 

       scope.$on('PlayPause',function(event, data){ 
        scope.doPlayPause(data.vlcPlayer, data.event) 
       }); 
    }; 
    return { 
myApp.directive('vlcControls', function ($compile, $rootScope, $timeout, $window, pictureboxConstants) { 


    var linker = function (scope, element, attrs) { 


       scope.getVLC = function (name) { 
        if ($window.document[name]) { 
         return $window.document[name]; 
        } 
        if ($window.navigator.appName.indexOf("Microsoft Internet") == -1) { 
         if ($window.document.embeds && $window.document.embeds[name]) 
          return $window.document.embeds[name]; 
        } else { 
         return $window.document.getElementById(name); 
        } 
       } 

       scope.doPlayPause = function (vlcPlayer, event) { 
        var vlc = scope.getVLC(vlcPlayer); 
        if (vlc) { 

         if (vlc.playlist.isPlaying) { 
          vlc.playlist.pause(); 
          angular.element(event.target).children().removeClass('fa fa-pause font-12'); 
          angular.element(event.target).children().addClass('fa fa-play font-12'); 

         } else { 
          if (vlc.audio.mute == true) { 
           //do something 
          } 
          vlc.playlist.play(); 
         } 
        } 
       } 

       scope.$on('PlayPause',function(event, data){ 
        scope.doPlayPause(data.vlcPlayer, data.event) 
       }); 
    }; 
    return { 
     restrict: "E", 
     link: linker 
    }; 
});  

另一種方法是使用一個工廠,共享controllerdirective的方法,

Check this so post for more details

+0

從控制器調用該指令時,動態設置一些DOM元素。這裏的問題是如何從該指令中調用特定的方法,假設我們不需要DOM操作,而只需要函數。 – Slimshadddyyy

+0

因爲'doPlayPause'是指令中的一個函數,所以'scope.doPlayPause(data.vlcPlayer,data.event)'只是調用那個沒有參數的函數,即scope.doPlayPause()。 – Sravan

+0

更新了我添加'vlcPlayerCustomTemplate'的指令。我不想要那個HTML,但只想從該指令中調用一個函數?如果我調用該指令,它也會附加我不想要的HTML,但只調用一個函數。 – Slimshadddyyy

0

有辦法做到這一點,其中之一是通過廣播事件,聽數它在指令

但是,我不知道整個上下文,你到底想要達到什麼,但它看起來像在設計中有一個小問題。我會問的問題是「你爲什麼要從父控制器的指令中調用方法?」理想情況下,當你使用指令時,它的功能是獨立的,如果你需要與外部世界進行交互,那麼你要麼通過變量綁定來實現,要麼像我之前提到的那樣通過事件來實現。

我確定有一種方法可以完全按照您的要求進行操作,但是如果給出信息中的信息,則不需要。

+0

假設指令''設置DOM元素可以重用一些函數。我們如何能夠從控制器調用指令中定義的函數? – Slimshadddyyy

+0

再次,類似於@Yatrix提到的,它看起來像一種代碼味道。您應該將整個結構視爲單獨的模塊,而每個模塊都有自己的元素。現在,對這些元素採取行動,在模塊內部做些事情。當發生什麼事情時,您可以播放任何對此感興趣的人都會聽到的事件。 –

0

您的目標是調用directive方法從controller沒有任何DOM操縱,您可以實現相同的幫助isolated scope下面。

您可以在您的directive中有一個isolated scope如下。

scope: { 
      /* This is the reference object passed from the controller */ 
      controllerRef: '=' 
     } 

然後你可以從controller傳遞相同的,

$scope.vlcControls = {}; 

$compile('<vlc-controls controller-ref="vlcControls"></vlc-controls>')($scope); 

然後你就可以分配方法將這些對象的指令,

 scope.controllerRef = scope.controllerRef || {}; 

     angular.extend(scope.controllerRef, { 
     doPlayPause: scope.doPlayPause, 
     // This is just for an example 
     callDirectiveFromController: scope.callDirectiveFromController 
     }); 

,您現在幾乎準備從控制器調用以下任何方法,如下所示:

$scope.vlcControls.callDirectiveFromController(); 

檢查下面的代碼並執行它的工作很好地爲你所期望:-)

var myApp = angular.module('myApp', []); 
 

 
myApp.controller('myModuleCtrl', function ($scope, $http, $controller, $compile) { 
 
    $scope.vlcControls = {}; 
 
    
 
    $compile('<vlc-controls controller-ref="vlcControls"></vlc-controls>')($scope); 
 
    
 
    $scope.vlcControls.callDirectiveFromController(); 
 

 
}); 
 

 
myApp.directive('vlcControls', function ($compile, $rootScope, $timeout, $window)//, pictureboxConstants) 
 
      { 
 

 

 
    var linker = function (scope, element, attrs) { 
 

 

 
       scope.getVLC = function (name) { 
 
        if ($window.document[name]) { 
 
         return $window.document[name]; 
 
        } 
 
        if ($window.navigator.appName.indexOf("Microsoft Internet") == -1) { 
 
         if ($window.document.embeds && $window.document.embeds[name]) 
 
          return $window.document.embeds[name]; 
 
        } else { 
 
         return $window.document.getElementById(name); 
 
        } 
 
       }; 
 

 
       scope.doPlayPause = function (vlcPlayer, event) { 
 
        var vlc = scope.getVLC(vlcPlayer); 
 
        if (vlc) { 
 

 
         if (vlc.playlist.isPlaying) { 
 
          vlc.playlist.pause(); 
 
          angular.element(event.target).children().removeClass('fa fa-pause font-12'); 
 
          angular.element(event.target).children().addClass('fa fa-play font-12'); 
 

 
         } else { 
 
          if (vlc.audio.mute == true) { 
 
           //do something 
 
          } 
 
          vlc.playlist.play(); 
 
         } 
 
        } 
 
       }; 
 
     
 
      scope.callDirectiveFromController = function() { 
 
       console.log('I called from the controller but executed inside the directive :-)'); 
 
      }; 
 
    
 
      scope.controllerRef = scope.controllerRef || {}; 
 

 
      angular.extend(scope.controllerRef, { 
 
      doPlayPause: scope.doPlayPause, 
 
      // This is just for an example 
 
      callDirectiveFromController: scope.callDirectiveFromController 
 
      }); 
 
    }; 
 
    return { 
 
     restrict: "E", 
 
     scope: { 
 
      /* This is the reference object passed from the controller */ 
 
      controllerRef: '=' 
 
     }, 
 
     link: linker 
 
    }; 
 
}); 
 

 
angular.bootstrap(document, ['myApp']);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 
<div ng-controller="myModuleCtrl"> 
 
</div>

相關問題