Controller and services are not loading in angularjs - angularjs

I have integrated requirejs with my angular app.
But while loading app, it gives me an error 'Argument 'appCtrl' is not a function, got undefined'
Here is my controller code :
define(['Angular'], function (angular) {
function appCtrl($scope, pathServices) {
alert('sa');
}
function homeCtrl($scope, brandService) {
console.log('dfd');
}
});
And along with this, it gives error for 'unknown provider pathServices'
Service code is :
serviceConfig.js
define([
'Angular',
'common/Services/services',
'current/js/services'
], function(angular, commonServices, loacalStorageServices, currentServices) {
"use strict";
var services = {
commonServices : commonServices,
currentServices : currentServices,
};
var initialize = function (angModule) {
angular.forEach(services,function(service, name) {
angModule.service(name, service);
});
}
return {
initialize: initialize
};
});
common/services.js
define(['Angular'], function (angular) {
var app = angular.module('myApp.services', []);
app.factory('pathServices', function($http, $q, $rootScope) {
function pathServices() {
alert('as');
}
return new pathServices();
});
app.factory('anotherServices', function($http, $q, $rootScope) {
function anotherServices() {
alert('as');
}
return new anotherServices();
});
});
current/services.js
define(['Angular'], function(angular) {
var app = angular.module('myApp.services', []);
app.factory('brandsService', function() {
function brandsService() {
var autoCompleteData = [];
this.getSource = function() {
return autoCompleteData;
}
this.setSource = function(states) {
autoCompleteData = states;
}
}
return new brandsService();
});
});
in serviceConfig.js I have included 2 service files.. But the problem is, the last current/service.js file overwrites all files.. How can I include multiple service files ?
I am new to requirejs. How can I use controller function and services using requirejs ?
Can anyone help ?

You have to declare your functions in the global (window) namespace, or register them in your module with the moduleName.controller('controllerName',controllerFn)
So either
define(['Angular'], function (angular) {
window.appCtrl = function($scope, pathServices) {
alert('sa');
}
window.homeCtrl = function($scope, brandService) {
console.log('dfd');
}
});
or
define(['Angular'], function (angular) {
var module = angular.module('theModuleName');
module.controller('appCtrl', function($scope, pathServices) {
alert('sa');
});
module.controller('homeCtrl', function($scope, brandService) {
console.log('dfd');
}
});
should fix this error (I prefer the second approach).

Related

Factory Service is always undefined

I've spent a few hours trying to debug this with no real breakthroughs. My console.logs correctly output the load order.
- app
- factory
- controller
I'm annotating my dependencies (even though I'm not minifying at the moment).
Is there anything obviously wrong here that I am missing?
error
app
(function () {
'use strict';
console.log("running app");
var app = angular.module('InventoryProductApp', []).config(function ($logProvider) {
$logProvider.debugEnabled(true);
});
angular.element(document).ready(function () {
var app = document.getElementById('InventoryProductApp');
angular.bootstrap(angular.element(app), ['InventoryProductApp']);
});
})();
controller
(function () {
'use strict';
angular.module('InventoryProductApp').controller("LocationsController", ['$scope', '$log', 'LocationsFactory'
, function ($scope, $http, $log, LocationsFactory) {
console.log("running controller");
$scope.locations = null;
$scope.loading = false;
//private methods -------------------------------------------------------------------------------------------------------------------------------------------------------------
var fetchLocationData = function (inventoryId) {
$scope.loading = true;
console.log(LocationsFactory);
var promise = LocationsFactory.getLocationData(inventoryId);
promise.then(function (data) {
$scope.loading = false;
if (data.success) {
$scope.locations = data.locations;
}
else
{
$log.error('There was an error getting location data');
}
}, function (data) {
$scope.loading = false;
$log.error('There was an error getting location data');
});
}
//end private methods ---------------------------------------------------------------------------------------------------------------------------------------------------------
//public methods --------------------------------------------------------------------------------------------------------------------------------------------------------------
var init = function (inventoryId) {
console.log('inventoryId', inventoryId);
fetchLocationData(inventoryId);
}
//end public methods ----------------------------------------------------------------------------------------------------------------------------------------------------------
init(inventoryId); // inventoryId is found in the partialView _inventoryLocationDistribution
}]);
})();
factory
(function () {
'use strict';
angular.module('InventoryProductApp').factory('LocationsFactory', ['$http', '$q', '$log', function ($http, $q, $log) {
console.log("running factory");
return {
getLocationData: function (inventoryId) {
var def = $q.defer();
$http.get('/butthead', {
params: {
inventoryId: inventoryId
}
}).then(function (response) {
def.resolve({
success: true,
locations: data.locations
});
}, function (response) {
$log.error('failed to fetch data', response);
def.resolve({
success: false,
redirect: response.redirect
});
});
return def.promise;
}
}
}]);
})();
script load order
<script src="~/theme/modern/assets/global/plugins/angularjs/angular.min.js"></script>
<script src="~/App/Inventory/Product/ProductApp.js"></script>
<script src="~/App/Inventory/Product/LocationsFactory.js"></script>
<script src="~/App/Inventory/Product/LocationsController.js"></script>
In your controller:
angular.module('InventoryProductApp').controller("LocationsController",
['$scope', '$log', 'LocationsFactory', function ($scope, $http, $log, LocationsFactory) {
You're missing '$http' in your dependency injections, which means the LocationsFactory argument isn't filled at all.

Unit Test for a scope that retrieves an integer (osVersion)

I am trying to write a unit test for a $scope that retrieves the customer's osVersion in a file called module.js.
Here is the function:
angular.module('app.customer-view', [])
.controller('customer-view.mainController', [
'$scope',
'$window',
'$document',
'customerViewService',
'app',
'customerViewConstants',
function ($scope, $window, $document, customerViewService, app, customerViewConstants) {
'use strict';
function getOSVersion() {
if (window.nativeBridge) {
return window.nativeBridge.deviceProfile.getOSVersion();
}
}
function init() {
$scope.osVersion = getOSVersion();
}
init();
}
]};
How to write a unit test that checks to see that $scope.osVersion return a version number as it should? This is what I have so far:
describe('customer-view.mainController', function () {
'use strict';
/* Variables directly derived from module.js */
var scope,
_window,
spec_customerService,
createController,
app,
customerViewConstants,
/* Extra dependencies required for unit test cases */
rootScope,
$controller,
stub,
deferredObj;
beforeEach(function(){
module('app.customer-view', 'senses');
stub = {
data: {
'osVersion': 4.02
}
};
inject(function($injector) {
$controller = $injector.get('$controller');
rootScope = $injector.get('$rootScope');
customerViewConstants = $injector.get('customerViewConstants');
spec_customerService = $injector.get('customerViewService');
deferredObj = $injector.get('$q');
app = {
setRadialHeaderData:function(){
}
};
_window = {
document: {
createEvent: function(){
return {initUIEvent : function(){}};
}
},
dispatchEvent: function(){}
};
createController = function() {
scope = rootScope.$new();
return $controller('customer-view.mainController', {
'$scope': scope,
'$window': _window,
'$document': _window.document,
'app': app
});
};
});
});
it('should get the OS version when native is present', function(){
spyOn(scope, 'osVersion');
createController();
scope.$apply();
expect(scope.osVersion).toEqual(stub.data.osVersion);
});
});
This test above is now returning: Error: osVersion() method does not exist in C:/xampp/htdocs/myProject/customer-view/senses/node_modules/jasmine-core/lib/jasmine-core/jasmine.js
I think there is something wrong with how you have declared your controller, your init function and init() call should live inside the main controller function you are passing in.
angular.module('app.customer-view', [])
.controller('customer-view.mainController', [
'$scope',
'$window',
'$document',
'customerViewService',
'app',
'customerViewConstants',
function ($scope, $window, $document, customerViewService, app, customerViewConstants) {
function getOSVersion() {
if (window.nativeBridge) {
return window.nativeBridge.deviceProfile.getOSVersion();
}
}
function init() {
$scope.osVersion = getOSVersion();
}
init();
}
]};
scope.osVersion cannot be spied, because the method doesn't exist on scope before controller constructor was called, and it was already called after calling $controller.
To be efficiently tested, osVersion should be extracted to separate service,
app.factory('osVersion', function ($window) {
if ($window.nativeBridge) {
return $window.nativeBridge.deviceProfile.getOSVersion();
}
});
This way it can be easily mocked on module or $controller level and tested with
var mockedOsVersion = {};
...
expect(scope.osVersion).toBe(mockedOsVersion);

Angular can not find my factory

So I created with angular a small factory to get my local json file now I wanna pass that data to my controller but it can't find the factory name and says 'unresolved variable'.
Here is the snippet of my code what I guess is relevant for now.
(function () {
var app = angular.module('locatieTool', ['ngRoute']);
app.controller('teamController', function ($scope) {
function init () {
dataFactory.getTeams().success(function(data) {
$scope.teams = data
});
}
init();
console.log($scope.teams);
});
// factory
app.factory('dataFactory', function($http) {
var team = {};
//get local data
team.getTeams = function() {
return $http.get ('http://localhost:4040/');
};
return team;
});
})();
My goal is just to console log the $scope.teams, than I can do more with the data.
you should include "dataFactory" inside your controller
(function () {
var app = angular.module('locatieTool', ['ngRoute']);
app.controller('teamController', function ($scope, dataFactory) {
function init () {
dataFactory.getTeams().success(function(data) {
$scope.teams = data
});
}
init();
console.log($scope.teams);
});
// factory
app.factory('dataFactory', function($http) {
var team = {};
//get local data
team.getTeams = function() {
return $http.get ('http://localhost:4040/');
};
return team;
}); })();
I believe you need to pass your factory into the controller:
app.controller('teamController', function ($scope, dataFactory) {
function init () {
dataFactory.getTeams().success(function(data) {
$scope.teams = data
});
}
init();
console.log($scope.teams);
});

Angular service which is a require js module, is not getting the injected dependencies

I have a module 'global.services' in which I registered a service "Restservices"
(function(define, angular) {
"use strict";
define(["global/services/restServices"],
function(RestServices) {
var moduleName = "global.services";
angular.module(moduleName, [])
.config(function(RestangularProvider) {
RestangularProvider.setBaseUrl('http://localhost:8888/src/app/data/');
RestangularProvider.setRequestSuffix('.json');
})
.factory('RestServices', RestServices);
return moduleName;
});
}(define, angular));
and my "RestService" is also a module
(function(define, angular) {
"use strict";
define(function() {
var restService = function($rootScope, Restangular) {
// body...
return {
getData: function(arg) {
// body...
$rootScope.$broadcast('gettingData');
return Restangular.oneUrl('listPanel');
}
}
};
return restService;
});
}(define, angular));
In the above service both $rootScope and Restangular are undefined.
Please tell me how to inject dependencies in this respect.
I found the reason of $rootScope and Restangular being undefined.
Factory registration is perfect but when I am trying to use it in a different module's controller I am injecting "global/services/restServices" instead of "global/services/services" which is the actual services module.
Previous code:
(function(define, angular) {
define(['global/services/restServices'], function(RestServices) {
var HeaderController = function($scope, $rootScope, $translate, $location, $document, RestServices) {
var user_modules = window.SESSION.getModules(),
modules = [];
angular.forEach(user_modules, function(moduleName) {
modules.push(window.CONFIG.MODULES[moduleName]);
});
RestServices.getData('webAppsData.json').get().then(function(d) {
if (d) {
if (d.response) {
$scope.webApps = d.response;
} else {
$scope.webApps = [];
}
} else {
$scope.webApps = [];
}
});
$scope.title = "Tumbler";
$scope.modules = modules;
};
return ["$scope", "$rootScope", "$translate", "$location", "$document", "RestServices", HeaderController];
})
}(define, angular));
Present code(working):
(function(define, angular) {
define(['global/services/services'], function() {
var HeaderController = function($scope, $rootScope, $translate, $location, $document, RestServices) {
var user_modules = window.SESSION.getModules(),
modules = [];
angular.forEach(user_modules, function(moduleName) {
modules.push(window.CONFIG.MODULES[moduleName]);
});
RestServices.getData('webAppsData.json').get().then(function(d) {
if (d) {
if (d.response) {
$scope.webApps = d.response;
} else {
$scope.webApps = [];
}
} else {
$scope.webApps = [];
}
});
$scope.title = "Tumbler";
$scope.modules = modules;
};
return ["$scope", "$rootScope", "$translate", "$location", "$document", "RestServices", HeaderController];
})
}(define, angular));
So, just inject the module and use its services.

Angularjs and qunit testing

I have a angularjs web application and want to use qunit for unit testing in it. I have a controller:
function RootCtrl($scope, $rootScope, $window, $location) {
// logger is empty at the start
$scope.logger = '';
// we have no login error at the start
$scope.login_error = '';
//
// Get values array of object
//
$rootScope.values = function (obj) {
var vals = [];
for( var key in obj ) {
if(key !== '$$hashKey' && key !== 'checked')
vals.push(obj[key]);
}
return vals;
}
}
Now i want to write unit test for values function with qunit. I included all js files to the test/index.html and qunit.css. Now my test.js has following content:
var injector = angular.injector(['ng', 'myApp']);
var init = {
setup : function () {
this.$scope = injector.get('$rootScope').$new();
}
}
module('RootCtrl', init);
test('RootCtrl', function(){
var $controller = injector.get('$controller');
$controller('RootCtrl', {
$scope : this.$scope,
$location : this.$location
});
equal(['value'], $controller.values({'key' : 'value'}))
});
But i'm getting error: http://docs.angularjs.org/error/$injector/unpr?p0=$rootElementProvider%20%3C-%20$rootElement%20%3C-%20$location%20%3C-%20$route at:
$controller('RootCtrl', {
$scope : this.$scope,
$location : this.$location
});
How to inject correctly controller and use $scope, $rootScope, $location and another services from it?
Thank you.
Try this instead of your controller
$controller('RootCtrl',['$scope', '$rootScope', '$location','$route', function ($scope, $rootScope, $location, $route) {
$scope : this.$scope,
$location : this.$location
}]);
Had similar problem, so since no other answer here.
I ended up using:
client side code:
var myApp= angular.module('myApp', []);
myApp.controller('myCtrl', function ($scope) {
//angular client side code
$scope.canSubmit = function () {
//some logic
return true;
}
}
Qunit tests:
var ctrl, ctrlScope, injector;
module("Testing the controller", {
setup: function () {
angular.module('myApp');
injector = angular.injector(['ng', 'myApp']);
ctrlScope = injector.get('$rootScope').$new();
ctrl = injector.get('$controller')('myCtrl', { $scope: ctrlScope });
ctrlScope.model = {
//model object
};
},
teardown: function () {
}
});
test("Given something happened then allow submit", function () {
ok(ctrlScope.someFunction(...), "some functionality happened");
equal(true, ctrlScope.canSubmit());
});
This blog post was useful.
One can easily inject more into the controller under test.

Resources