src/xing-frontend-utils/components/toast/compiler.js
function xngCompilerService($q, $http, $injector, $compile, $controller, $templateCache) {
/**
* @ngdoc service
* @name $xngCompiler
* @module xng.services.compiler
*
* @description
* The $xngCompiler service is an abstraction of angular's compiler, that allows the developer
* to easily compile an element with a templateUrl, controller, and locals.
*/
/**
* @ngdoc method
* @name $xngCompiler#compile
* @param {object} options An options object, with the following properties:
*
* - `controller` – `{(string=|function()=}` – Controller fn that should be associated with
* newly created scope or the name of a {@link angular.Module#controller registered
* controller} if passed as a string.
* - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be
* published to scope under the `controllerAs` name.
* - `template` – `{string=}` – html template as a string or a function that
* returns an html template as a string which should be used by {@link
* ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
* This property takes precedence over `templateUrl`.
*
* - `templateUrl` – `{string=}` – path or function that returns a path to an html
* template that should be used by {@link ngRoute.directive:ngView ngView}.
*
* - `transformTemplate` – `{function=} – a function which can be used to transform
* the templateUrl or template provided after it is fetched. It will be given one
* parameter, the template, and should return a transformed template.
*
* - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
* be injected into the controller. If any of these dependencies are promises, the compiler
* will wait for them all to be resolved or one to be rejected before the controller is
* instantiated.
*
* - `key` – `{string}`: a name of a dependency to be injected into the controller.
* - `factory` - `{string|function}`: If `string` then it is an alias for a service.
* Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}
* and the return value is treated as the dependency. If the result is a promise, it is
* resolved before its value is injected into the controller.
*
* @returns {object=} promise A promsie which will be resolved with a `compileData` object,
* with the following properties:
*
* - `{element}` – `element` – an uncompiled angular element compiled using the provided template.
*
* - `{function(scope)}` – `link` – A link function, which, when called, will compile
* the elmeent and instantiate options.controller.
*
* - `{object}` – `locals` – The locals which will be passed into the controller once `link` is
* called.
*
* @usage
* $xngCompiler.compile({
* templateUrl: 'modal.html',
* controller: 'ModalCtrl',
* locals: {
* modal: myModalInstance;
* }
* }).then(function(compileData) {
* compileData.element; // modal.html's template in an element
* compileData.link(myScope); //attach controller & scope to element
* });
*/
this.compile = function(options) {
var templateUrl = options.templateUrl;
var template = options.template || '';
var controller = options.controller;
var controllerAs = options.controllerAs;
var resolve = options.resolve || {};
var locals = options.locals || {};
var transformTemplate = options.transformTemplate || angular.identity;
// Take resolve values and invoke them.
// Resolves can either be a string (value: 'MyRegisteredAngularConst'),
// or an invokable 'factory' of sorts: (value: function ValueGetter($dependency) {})
angular.forEach(resolve, function(value, key) {
if (angular.isString(value)) {
resolve[key] = $injector.get(value);
} else {
resolve[key] = $injector.invoke(value);
}
});
//Add the locals, which are just straight values to inject
//eg locals: { three: 3 }, will inject three into the controller
angular.extend(resolve, locals);
if (templateUrl) {
resolve.$template = $http.get(templateUrl, {cache: $templateCache})
.then(function(response) {
return response.data;
});
} else {
resolve.$template = $q.when(template);
}
// Wait for all the resolves to finish if they are promises
return $q.all(resolve).then(function(locals) {
var template = transformTemplate(locals.$template);
var element = angular.element('<div>').html(template).contents();
var linkFn = $compile(element);
//Return a linking function that can be used later when the element is ready
return {
locals: locals,
element: element,
link: function link(scope) {
locals.$scope = scope;
//Instantiate controller if it exists, because we have scope
if (controller) {
var ctrl = $controller(controller, locals);
//See angular-route source for this logic
element.data('$ngControllerController', ctrl);
element.children().data('$ngControllerController', ctrl);
if (controllerAs) {
scope[controllerAs] = ctrl;
}
}
return linkFn(scope);
}
};
});
};
}
angular.module(`xing.utils.compiler`, [
])
.service('$xngCompiler', [
'$q',
'$http',
'$injector',
'$compile',
'$controller',
'$templateCache',
xngCompilerService
]);