2

I encounter an issue when trying to manually use angular.injector to inject a service which is opening a dialog, which in turn, uses inside it's template a directive, which uses a dynamic template.

The errors I have in the console are:

1: Unknown provider: $rootElementProvider <- $rootElement <- $location <- $anchorScroll <- ngIncludeDirective <- $location

2: Controller 'ngInclude', required by directive 'ngInclude', can't be found!

Here is the plunker demonstrating the problem

var customSvc = angular.injector(['ng', 'pluginApp']).get("customSvc");
customSvc.testOpenDialog(100, scope);

I also tried building the url and specifying it as a directive attribute and accessing it from the templateUrl function, but also in this case it fails, because the value I receive is just the name of the variable, not the content.

If I avoid injection of the service via angular.injector, the code works, however due to the nature of the application I can't avoid it, besides, I am interested in understanding what is the behind reason of this error, if anyone is kind enough to shed some light into the matter.

4
  • You want to access "customSvc" service in your directive, right? Commented Sep 26, 2016 at 6:47
  • I already access it via angular.injector function and it works, the problem is in the sampleDirective, because over there, ng-include is not working Commented Sep 26, 2016 at 7:04
  • In sampleDirective, why you are using ng-include in template, and the file you are including don't have extension?template: "<div ng-include='sampleLinkTemplate'></div>" , use templareUrl:"sampleLinkTemplate.html" Commented Sep 26, 2016 at 7:14
  • Because it uses the value of the variable from the scope which is set in the link function. It's a way of using "dynamic template" based on a variable present in the scope Commented Sep 26, 2016 at 7:23

2 Answers 2

2

The solution is to inject the service in the following way:

   var customSvc = angular.injector(['ng', 'pluginApp', 
      function($provide) {
        var $rootElement = angular.element(document.querySelector('body'));
        $provide.value('$rootElement', $rootElement);
      }]).get("customSvc");

Here is the working plunker

Sign up to request clarification or add additional context in comments.

Comments

0

In your, gedContextMenu.js file, do following changes

Inject pluginApp

angular.module('gedContextMenuApp', ['ui.bootstrap', 'mgcrea.ngStrap.popover','pluginApp']);

Inject service customSvc in your gedContextMenu menu directive,

angular.module('gedContextMenuApp').directive('gedContextMenu',['$log','$templateCache', '$uibModal', 'customSvc', function($log, $templateCache, $uibModal, customSvc) {
  return {
    restrict: 'AE',
    scope: {
      gedContextData: '='
    },
    template: "<button class='fa fa-cog' bs-popover data-template='{{popoverTemplate}}' data-auto-close='1' data-placement='bottom' data-animation='am-flip-x'></button>",
    controller: function($scope) {
      $scope.popoverTemplate = 'popoverTemplate.html';

      $scope.executePlugin = function($event, contextItem) {
        var propName = contextItem.action;
        $scope.contextItem = contextItem;
        $log.info('property name ' + propName + ' used to trigger event ', $event.type);
        $scope[propName] = $event;
      }

      $scope.click = function($event, contextItem) {
        $scope.executePlugin($event, contextItem);
      }
    },
    link: function(scope, element, attrs) {
        scope.$watch('openDialog', function(event) {
        if (event && event.type === 'click') {
          console.log(customSvc);
          // var customSvc = angular.injector(['ng', 'pluginApp']).get("customSvc");

          //angular.injector(['ng', function($provide) {
          //  var $rootElement = angular.element(document.querySelector('body'));
          //  $provide.value('$rootElement', $rootElement);
          //}]).invoke(function($injector) {
          //  var localRootElement = $injector.get('$rootElement');
          //});

          // customSvc.testOpenDialog(100, scope);
          //customSvc.testDirettivaConfirm(100, scope);

        }
      });
    }
  }
}]);

1 Comment

Like I said in my question, if I bypass the manual use of the injector, it works, but I can't do that in my app because actions.js is loaded dynamically and I don't know at the gedContextMenu directive level what services it will use or not use. The plunker I posted was just a simplification of the problem. Regardless, I still need to make it work with manual use of angular.injector or understand if it's not possible due to some limitations

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.