Search code examples
angularjsangular-http

Can't send a POST request with $http in Angular - ReferenceError: $http is not defined


So I keep getting this ReferenceError: $http is not defined, even though I have included $http in the controller, which seems to be the most common cause of this error message. I've tried also passing $http into the function itself, but that doesn't solve it.

I feel like I am missing something SUPER obvious, so any help would be much appreciated, thank you!

I've included the entire script, just for clarity's sake. You can see the post request towards the end of the script, inside the finaliseDay function.

Thanks!

Here is the error:

ReferenceError: $http is not defined
    at l.$scope.finaliseDay (http://localhost:8888/goalzy.js:69:12)
    at ib.functionCall (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js:198:303)
    at Dc.(anonymous function).compile.d.on.f (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js:214:485)
    at l.$get.l.$eval (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js:125:305)
    at l.$get.l.$apply (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js:126:6)
    at HTMLAnchorElement.<anonymous> (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js:215:36)
    at HTMLAnchorElement.c (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js:32:389)angular.js:11607 (anonymous function)angular.js:8557 $getangular.js:14502 $get.l.$applyangular.js:21440 (anonymous function)angular.js:3014 c

Here is the HTML first

<!doctype html>
<html ng-app="goalzy">
   <head>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js"></script>
      <script src="goalzy.js"></script>
   </head>
   <body>
      <div class="container">
         <div class="well">
            <h2>Goalzy</h2>

            Dev TODO
            <ul>
               <li>Hook up the API to persist data</li>
            </ul>

            <div ng-controller="TodoController">
               <span>{{remaining()}} of {{todos.length}} remaining today</span>
               <span>You're at {{percentComplete()}}% completion</span>
               [ <a href="" ng-click="finaliseDay(percentComplete())">finalise day</a> ]
               <ul class="unstyled">
                  <li ng-repeat="todo in todos">
                     <input type="checkbox" ng-model="todo.done">
                     <span class="done-{{todo.done}}">{{todo.text}}</span>
                  </li>
               </ul>
               <form ng-submit="addTodo()">
                  <input type="text" ng-model="todoText"  size="30"
                     placeholder="add new todo here">
                  <input class="btn-primary" type="submit" value="add">
               </form>
               <hr>
               <div class="historial" ng-repeat="h in historicalDailyPercentages">
                  <ul>
                    <li>Date: {{h.date}}</li>
                    <li>Percentage of Daily Tasks Completed: {{h.percent}}%</li>
                    <li><div>Tweet it!</div></li>
                  </ul>

               </div>
            </div>
         </div>
      </div>
      </div>
   </body>


</html>

And here is the JS:

//Goalzy.js

angular.module('goalzy', [])

 .config(['$httpProvider', function($httpProvider) {
      $httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
   });

  .controller('TodoController', ['$scope','$http', function($scope, $http) {
$scope.todos = [];

$scope.historicalDailyPercentages = [];

$scope.addTodo = function() {

  if ($scope.todoText != "") {
    if ($scope.todos.length < 3) {
        $scope.todos.push({text:$scope.todoText, done:false});
        $scope.todoText = '';   

      //Save to DB

    }
    else {
        alert("You can only have 3 todos per day!");
      $scope.todoText = '';
    }   
  } else {
    alert("you must write something");
  }

};

$scope.remaining = function() {
  var count = 0;
  angular.forEach($scope.todos, function(todo) {
    count += todo.done ? 0 : 1;
  });
  return count;
};

$scope.percentComplete = function() {
    var countCompleted = 0;
    angular.forEach($scope.todos, function(todo) {
      countCompleted += todo.done ? 1 : 0; //Simply calculates how many tasks have been completed
    console.log(countCompleted);
    });

  var totalCount = $scope.todos.length;
  var percentComplete = countCompleted / totalCount * 100;
  return percentComplete;
}


$scope.finaliseDay = function(percentComplete) {
    alert("You're finalising this day with a percentage of: " + percentComplete);
    var today = new Date();
    var alreadyPresent = $scope.historicalDailyPercentages.some(function (item) { 
        return item.date.getFullYear() === today.getFullYear() &&
               item.date.getMonth() === today.getMonth() &&
               item.date.getDate() === today.getDate();
    });

    //Confirm that nothing has alreayd been posted for today
    if (!alreadyPresent) {
        $scope.historicalDailyPercentages.push({
            percent: percentComplete,
            date: today
        });

        // Simple POST request example (passing data) :
        $http.post('/api/postDailyPercentage.php', {msg:'hello word!'}).
          success(function(data, status, headers, config) {
            // this callback will be called asynchronously
            // when the response is available
            console.log("data" + data);
          }).
          error(function(data, status, headers, config) {
            // called asynchronously if an error occurs
            // or server returns response with an error status.
            console.log("data" + data);
          });

    }
    else {
      alert("You're all set for today - see you tomorrow!");
    }

    console.log($scope.historicalDailyPercentages);
}


  }]);

Solution

  • Provider won't be available inside controller with suffix 'Provider', you can do access them by provider name only here it would be $http only, also remove ; after config initialization

    $httpProvider setting should be done inside the angular config phase

    CODE

    angular.module('goalzy', [])
    .config(['$httpProvider', function($httpProvider) {
        $httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
    }]);
     .controller('TodoController', ['$scope', '$http', function($scope, $http) {
        //controller code here
    }]);
    

    Note: For sure you should remove $httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8'; line from controller

    Working Plunkr