指令
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
html元素或任何doPlayPause
操作的情况下,仅从controller
调用特定vlcPlayerCustomTemplate
函数/方法DOM
的最佳方法是什么?< / p>
答案 0 :(得分:1)
您应该使用$broadcast
和$on
来处理从控制器到指令的通信。
对我而言,这是一种代码味道。如果在父范围和指令范围之间共享某些内容,则应通过绑定来完成。如果你必须使用这样的pub-sub模式,你应该重新考虑如何使用你的指令IMO。
你的指令应该能够做任何需要的事情,而不是直接从父控制器调用。如果父控制器需要它,它应该使用属性或非隔离范围绑定。
答案 1 :(得分:0)
一种方法是$broadcast
从controller
到directive
的事件并听取指令。
您甚至可以通过它以对象的形式发送参数。
$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
};
});
另一种方法是使用工厂并在controller
和directive
之间共享方法,
答案 2 :(得分:0)
有很多方法可以做到这一点,其中一种是通过广播一个事件并在指令中听取它
但是,我不知道整个上下文以及您想要实现的目标,但看起来设计中存在一个小问题。我要问的问题是“你为什么要在父控制器的指令中调用一个方法?”理想情况下,当你使用指令时,它的功能是自包含的,如果你需要与外部世界交互,那么你要么通过变量绑定,要么就像我已经提到的那样,事件。
我确信有一种方法可以完全按照你的意愿行事,但鉴于帖子中的信息,没有必要。
答案 3 :(得分:0)
您的目标是在没有任何directive
操作的情况下调用controller
中的DOM
方法,您可以在isolated scope
的帮助下实现相同的操作,如下所示。
您的isolated scope
可以有directive
,如下所示。
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>