Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - $q undefined in a directive

I'm trying to inject $q into my directive, but though $q is defined as a resolver() at first, when calling the function it is undefined. Maybe something related to binding? I don't know.

(function () {
'use strict';
  myForm.$inject = ["$q"];
  angular
    .module('myModule')
    .directive('myForm', myForm);

  function myForm($q) {
    return {
      restrict: 'EA',
      scope: {
        ngSubmitFunction: '&',
      },
      templateUrl: 'myTemplate',
      controllerAs: 'ctrl',
      controller: ["$scope", "$window", "$q", function ($scope, $window, $q) {
        var vm = this;
        vm.name = 'myForm';

        $scope.submitPromise = function(){};
        vm.ngSubmit = ngSubmit;
        function ngSubmit($form) {
          vm.submitDisabled = true;
          $form.$setSubmitted();
          if ($form.$valid) {
            $scope.submitPromise().then(function() {
                vm.submitDisabled = false;
            });
          }
        }
      }],
      link: function (scope, element, attrs) {
        console.log($q);
        scope.submitPromise = function($q) {
            console.log($q);
            var deferred = $q.defer();
            scope.ngSubmitFunction();
            return deferred.promise;
        }
      }
    };
  }
}());

The objective is to call ngSubmit when user clicks on a button. ngSubmit disables the button, waits for the async calls to be over and then enables the button.

In the example code, the 1st console.log($q) (executed when loading the page) outputs this:

Q(resolver) { if (!isFunction(resolver)) { throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver); }...

Which to me looks like correct. But when calling submitPromise() after pressing the button, this is the output:

undefined

TypeError: Cannot read property 'defer' of undefined

When is $q lost?

Note: this is not the only version I tried, originally all code was on controller, nothing on link. I've also been told this pattern is deprecated and to use this one, which is better:

function submitPromise($q) {
  return $q(function (resolve) {
    $scope.ngSubmitFunction();
  })
}

Nothing worked. Everything produces the same error, $q gets undefined at some point and can't find out why.

like image 350
p4x Avatar asked May 15 '26 01:05

p4x


2 Answers

Using $q as an argument parameter is causing $q to become undefined.

  myForm.$inject = ["$q"];
  angular
    .module('myModule')
    .directive('myForm', myForm);

  function myForm($q) {
    return {
      link: function (scope, element, attrs) {
        console.log($q);
        //scope.submitPromise = function($q) {
        //Remove $q as parameter
        scope.submitPromise = function() {
            console.log($q);
            var deferred = $q.defer();
            //scope.ngSubmitFunction();
            deffered.resolve(scope.ngSubmitFunction());
            return deferred.promise;
        }
      }

The myForm function is a directive construction function to which the AngularJS framework will inject service providers. But the submitPromise function is not injectable; it is a child function of myForm. All injections should be done in the parent function.


Also the code can be simplified by using $q.when to create a promise.

  link: function (scope, element, attrs) {
    console.log($q);
    //scope.submitPromise = function($q) {
    //Remove $q as parameter
    scope.submitPromise = function() {
        console.log($q);
        return $q.when(scope.ngSubmitFunction());
    }
  }
like image 114
georgeawg Avatar answered May 17 '26 13:05

georgeawg


You should solve with this different injection

(function () {
'use strict';

  angular
    .module('myModule')
    .directive('myForm', ['$q', function($q){

      return {
        . . .
      }

  }]);

Hope I've been helpful.

like image 39
AndreaM16 Avatar answered May 17 '26 15:05

AndreaM16