Harshit Laddha
Harshit Laddha

Reputation: 2124

Angularjs how to resolve unknown provider error in a directive

I am getting the following error in my meanjs app -

Error: [$injector:unpr] Unknown provider: $scopeProvider <- $scope <- uiJqDirective
http://errors.angularjs.org/1.4.7/$injector/unpr?p0=%24scopeProvider%20%3C-%20%24scope%20%3C-%20uiJqDirective
    at REGEX_STRING_REGEXP (angular.js:68)
    at angular.js:4289
    at Object.getService [as get] (angular.js:4437)
    at angular.js:4294
    at getService (angular.js:4437)
    at Object.invoke (angular.js:4469)
    at angular.js:7080
    at forEach (angular.js:336)
    at Object.<anonymous> (angular.js:7078)
    at Object.invoke (angular.js:4478)

I have a ui-jq directive which is as follows -

'use strict';

/**
 * 0.1.1
 * General-purpose jQuery wrapper. Simply pass the plugin name as the expression.
 *
 * It is possible to specify a default set of parameters for each jQuery plugin.
 * Under the jq key, namespace each plugin by that which will be passed to ui-jq.
 * Unfortunately, at this time you can only pre-define the first parameter.
 * @example { jq : { datepicker : { showOn:'click' } } }
 *
 * @param ui-jq {string} The $elm.[pluginName]() to call.
 * @param [ui-options] {mixed} Expression to be evaluated and passed as options to the function
 *     Multiple parameters can be separated by commas
 * @param [ui-refresh] {expression} Watch expression and refire plugin on changes
 *
 * @example <input ui-jq="datepicker" ui-options="{showOn:'click'},secondParameter,thirdParameter" ui-refresh="iChange">
 */
angular.module('ui.jq', ['ui.load']).
  value('uiJqConfig', {}).
  directive('uiJq', ['$scope', 'uiJqConfig', 'JQ_CONFIG', 'uiLoad', '$timeout', function uiJqInjectingFunction($scope, uiJqConfig, JQ_CONFIG, uiLoad, $timeout) {

  return {
    restrict: 'A',
    compile: function uiJqCompilingFunction(tElm, tAttrs) {

      if (!angular.isFunction(tElm[tAttrs.uiJq]) && !JQ_CONFIG[tAttrs.uiJq]) {
        throw new Error('ui-jq: The "' + tAttrs.uiJq + '" function does not exist');
      }
      var options = uiJqConfig && uiJqConfig[tAttrs.uiJq];

      return function uiJqLinkingFunction($scope, elm, attrs) {

        function getOptions(){
          var linkOptions = [];

          // If ui-options are passed, merge (or override) them onto global defaults and pass to the jQuery method
          if (attrs.uiOptions) {
            linkOptions = $scope.$eval('[' + attrs.uiOptions + ']');
            if (angular.isObject(options) && angular.isObject(linkOptions[0])) {
              linkOptions[0] = angular.extend({}, options, linkOptions[0]);
            }
          } else if (options) {
            linkOptions = [options];
          }
          return linkOptions;
        }

        // If change compatibility is enabled, the form input's "change" event will trigger an "input" event
        if (attrs.ngModel && elm.is('select,input,textarea')) {
          elm.bind('change', function() {
            elm.trigger('input');
          });
        }

        // Call jQuery method and pass relevant options
        function callPlugin() {
          $timeout(function() {
            elm[attrs.uiJq].apply(elm, getOptions());
          }, 0, false);
        }

        function refresh(){
          // If ui-refresh is used, re-fire the the method upon every change
          if (attrs.uiRefresh) {
            $scope.$watch(attrs.uiRefresh, function() {
              callPlugin();
            });
          }
        }

        if ( JQ_CONFIG[attrs.uiJq] ) {
          uiLoad.load(JQ_CONFIG[attrs.uiJq]).then(function() {
            callPlugin();
            refresh();
          }).catch(function() {

          });
        } else {
          callPlugin();
          refresh();
        }
      };
    }
  };
}]);

I have tried to load $scope with the directive, but I think I have done it wrongly. Can anyone suggest what am I doing wrong or where else should i look to find the correct problem

Upvotes: 1

Views: 2176

Answers (2)

ryeballar
ryeballar

Reputation: 30098

You don't have to inject scope in your directive, simply remove $scope in the array.

directive('uiJq', [
  '$scope', // YOU HAVE TO REMOVE THIS!
  'uiJqConfig', 
  'JQ_CONFIG', 
  'uiLoad', 
  '$timeout', 
  function uiJqInjectingFunction(
    $scope, // REMOVE THIS AS WELL
    uiJqConfig, 
    JQ_CONFIG, 
    uiLoad, 
    $timeout) { 

     /* ... */ 

  }])

You already have the scope of the directive inside the linking function returned by your compile function

return function uiJqLinkingFunction($scope, elm, attrs) {
  /* ... */
};

So your directive should only have these injected:

directive('uiJq', [
  'uiJqConfig', 
  'JQ_CONFIG', 
  'uiLoad', 
  '$timeout', 
  function (
    uiJqConfig, 
    JQ_CONFIG, 
    uiLoad, 
    $timeout) { 

     /* ... */ 

  }])

Upvotes: 1

www.admiraalit.nl
www.admiraalit.nl

Reputation: 6089

Do not inject $scope. Instead, replace compile by link, which has the scope as its first parameter:

link: uiJqLinkingFunction(scope, tElm, tAttrs) {

Upvotes: 1

Related Questions