Reputation: 577
My goal is to create an Angular module that displays popup dialog messages. This module contains a directive (HTML, CSS and JavaScript) containing the internal logic (and markup and styles). Plus there's a service (factory) which acts as an API that can be used by other services.
Now this service of course has an openDialog()
function which should insert the dialog directive into the DOM and present it to the user.
All solutions to this problem I have found so far make use of the $compile
function. But it needs scope
as a parameter. In a service where there's no scope
though. They only exist in controller
or link
functions.
The reason I chose this implementation is for separation of concerns (directive's link
and controller
for internal usage, factory
for external usage because it can be dependency injected). I know I could pass the scope
when calling the function like this:
popupDialogService.openDialog({ /* options */ }, $scope);
But I don't see the point. It doesn't feel right. What if I call that function from inside another service which doesn't use scope
either?
Is there a way to easily put the directive into the DOM from inside the service function or is there a better way to solve this problem?
Another solution I'm thinking about is calling a function of the directive's controller
from inside the directive's factory
. Is that possible?
angular.module('popupDialog').directive('popupDialog', directive);
function directive() {
return { ... };
}
angular.module('popupDialog').factory('popupDialogService', factory);
function factory() {
return { openDialog, closeDialog }; // *ES2015
function openDialog(options) {
// this function should put the `popupDialog` directive into the DOM
}
function closeDialog() {
// and this one should remove it
}
}
angular.module('myApp').factory('someRandomService', factory);
factory.$inject = ['popupDialogService'];
function factory(popupDialogService) {
return { clickedButton };
function clickedButton() {
popupDialogService.openDialog({ /* options */ });
// Sample implementation.
// It shouldn't matter where this function is beeing called in the end.
}
}
Upvotes: 2
Views: 676
Reputation: 193281
I know I could pass the scope when calling the function ... And it doesn't feel right.
Well you anyway need scope for dialog HTML content, Angular needs to compile and render it in some scope, right? So you have to provide scope object for your template somehow.
I suggest you to take a look at popular modal implementations like they do it, for example Angular UI Bootstrap's $modal or this simple one I was creating for my needs. The common pattern is passing scope parameter with modal initialization or use new child scope of the $rootScope
for dialog. This is the most flexible way that should work for your both cases.
After all, it's not necessarily has to be real scope instance. You can even make your service accept plain javascript object and use it to extend new $rootScope.$new()
object with.
Upvotes: 1