pbordeaux
pbordeaux

Reputation: 465

Issue using services in angular v 1.2.19

I am getting this error:

TypeError: Cannot read property 'prototype' of undefined
at Object.instantiate (http://localhost:3000/angular/angular.min.js:35:144)
at Object.<anonymous> (http://localhost:3000/angular/angular.min.js:35:435)
at Object.d [as invoke] (http://localhost:3000/angular/angular.min.js:35:36)
at http://localhost:3000/angular/angular.min.js:36:288
at c (http://localhost:3000/angular/angular.min.js:34:305)
at d (http://localhost:3000/angular/angular.min.js:35:6)
at Object.instantiate (http://localhost:3000/angular/angular.min.js:35:165)
at $get (http://localhost:3000/angular/angular.min.js:67:421)
at link (http://localhost:3000/lib/angular-route.min.js:7:248)
at K (http://localhost:3000/angular/angular.min.js:54:390)

I have checked my getter/setter syntax many times because I have seen others with this same issue. To my knowledge, mine is correct. Here is my code: Main module app.js:

angular.module('loc8rApp', ['ngRoute']);

function config ($routeProvider){
  $routeProvider 
.when('/', {
  templateUrl: 'home/home.view.html',
  controller: 'homeCtrl',
  controllerAs: 'vm'
})
.otherwise({redirectTo: '/'});
};

angular
  .module('loc8rApp')
  .config(['$routeProvider', config]);

Service loc8rData.js:

angular
  .module('loc8rApp')
  .service('loc8rData', loc8rData);

var loc8rData = function ($http) {
  var locationByCoords = function (lat, lng) {
    return $http.get('/api/locations?lng=' + lng + '&lat=' + lat + '&maxDistance=20');
  };
  return {
locationByCoords : locationByCoords
  };
}

Second service: geolocation.services.js:

angular
  .module('loc8rApp')
  .service('geolocation', geolocation);

var geolocation = function () {
  var getPosition = function (cbSuccess, cbError, cbNoGeo) {
    if (navigator.geolocation) {
  navigator.geolocation.getCurrentPosition(cbSuccess, cbError);
}
else {
  cbNoGeo();
}
 };
      return {
    getPosition : getPosition
  };
}

Controller homeCtrl.js:

angular
  .module('loc8rApp')
  .controller('homeCtrl', homeCtrl);
function homeCtrl ($scope, loc8rData, geolocation) { 
  var vm = this;
  vm.pageHeader = {
    title: 'Loc8r',
    strapline: 'Find places to work with wifi near you!'
  };
  vm.sidebar = {
    content: "Looking for wifi and a seat? Etc etc"
  };
  vm.message = "Checking your location";
  vm.getData = function (position) { 
var lat = position.coords.latitude, 
    lng = position.coords.longitude; 
vm.message = "Searching for nearby places"; 
loc8rData.locationByCoords(lat, lng) 
  .success(function(data) { 
    vm.message = data.length > 0 ? "" : "No locations found nearby";
    vm.data = { locations: data }; 
    }) 
  .error(function (e) { 
    vm.message = "Sorry, something's gone wrong"; 
    }); 
  }; 
  vm.showError = function (error) { 
    $scope.$apply(function() { 
      vm.message = error.message; 
    }); 
  }; 
  vm.noGeo = function () { 
$scope.$apply(function() { 
  vm.message = "Geolocation is not supported by this browser."; 
}); 
  }; 
  geolocation.getPosition(vm.getData,vm.showError,vm.noGeo); 
}

In Layout.jade I have:

 html(ng-app='loc8rApp')

and in the body:

    .containter
      div(ng-view)
        block content

and then I have my scripts aligned with body

body

....

script(src='//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js')
script(src='/angular/angular.min.js')
script(src='/lib/angular-route.min.js')
script(src='/bootstrap/js/bootstrap.min.js')
script(src='/javascript/validation.js')
script(src='/app.js')
script(src='/common/services/loc8rData.js')
script(src='/common/services/geolocation.service.js')
script(src='/home/homeCtrl.js')

The HTML:

<div id="banner" class="page-header">
  <div class="row">
    <div class="col-lg-6"></div>
    <h1>{{ vm.pageHeader.title }} 
      <small>{{ vm.pageHeader.strapline }}</small> 
    </h1>
  </div>
</div>
<div class="row">
  <div class="col-xs-12 col-sm-8">
    <label for="filter">Filter results</label>
    <input id="filter" type="text", name="filter", ng-model="textFilter">
    <div class="error">{{ vm.message }}</div>
    <div class="row list-group">
      <div class="col-xs-12 list-group-item" ng-repeat="location in   vm.data.locations | filter : textFilter">
      <h4>
        <a href="/location/{{ location._id }}">{{ location.name }}</a>
        <small class="rating-stars" rating-stars rating="location.rating">    </small>
        <span class="badge pull-right badge-default">{{ location.distance }}  </span>
      </h4>
      <p class="address">{{ location.address }}</p>
      <p>
            <span class="label label-warning label-facility" ng-  repeat="facility in location.facilities">
        {{ facility }}
      </span>
    </p>
  </div>
</div>
</div>
<div class="col-xs-12 col-sm-4">
      <p class="lead">{{ vm.sidebar.content }}</p> 
</div>
</div>

I have searched this high and low and so has my buddy. Know this is a long post, but if you're up for it, that would be pretty cool. thanks

Upvotes: 1

Views: 192

Answers (2)

M.Z.
M.Z.

Reputation: 474

The previous answer is totally correct. This is because of hoisting in Javascript. Variable declarations and and function declarations are moved to the top of their respective scopes, but variable assignments are not. Therefore, if it was function declaration, not function expression as it is in the example, it would work.

var x; // variable declaration
x = 3; // variable assignment
var geolocation = function () { // function expression
//....
}
function geolocation() { // function declaration
//....
}

So for example in var x = 3; Javascript engine sees it as two separate statements. var x; in compiling time and x = 3; at execution time. Therefore, the function expression declaration was hoisted, however the assignment of the function expression was not.

Upvotes: 0

Stefano Dalpiaz
Stefano Dalpiaz

Reputation: 1673

You are declaring two of your functions as variables, but you are using them before they are defined. For example:

angular.module('loc8rApp').service('geolocation', geolocation);
var geolocation = function () {
    //....
}

In this case, when the first line tries to use the function geolocation, it is still undefined. If you use the other notation for declaring functions it will work:

angular.module('loc8rApp').service('geolocation', geolocation);
function geolocation() {
    //....
}

This is because the functions declared in this way are processed before the rest of the code.

Th same thing applies to your loc8rData function.

Upvotes: 2

Related Questions