Getting Jasmine to Work with Angular JS - javascript

I am trying to get Jasmine to work with my Angular JS Project But I always keep getting the following error. I am trying to get it to run a very very simple test. Also I have setup the angular js project using RequireJS. I have given my code below.
The Error I get is :
My Very Simple TestSpec is as given below :
describe('Controller:UserController', function () {
var scope,controller;
beforeEach(function () {
module('app');
inject(function ($controller,$rootScope) {
scope = $rootScope.$new();
controller = $controller('UserController', { '$scope': scope });
});
});
it('checks the troller name', function () {
expect(scope.name).toBe('Superhero');
});
});
And My Controller code is as given below :
define(['app','WebCallManager'], function (app) {
app.controller('UserController', function ($scope,$location,webcallService) {
$scope.name = 'Superhero';
$scope.loginUser = function(){
console.log("Login User Called...");
$location.path('/login').replace();
console.log("View Navigated...");
};
$scope.slidePanel = function(){
f7.openPanel('left');
};
$scope.doWebCall = function(){
console.log("Doing the Web Call...");
webcallService.sendGetRequest();
};
});
});
And the TestRunner.html is :
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Jasmine Test Runner v2.0.1</title>
<link rel="shortcut icon" type="image/png" href="framework/lib/jasmine-2.0.1/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="framework/lib/jasmine-2.0.1/jasmine.css">
<!-- Jasmine/Angular testing framework libraries -->
<script type="text/javascript" src="framework/lib/jasmine-2.0.1/jasmine.js"></script>
<script type="text/javascript" src="framework/lib/jasmine-2.0.1/jasmine-html.js"> </script>
<script type="text/javascript" src="framework/lib/jasmine-2.0.1/boot.js"></script>
<script type="text/javascript" src="framework/lib/angular.js"></script>
<script type="text/javascript" src="framework/lib/angular-mocks.js"></script>
<!-- include source files here... -->
<script data-main="main" src="framework/lib/require.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="UserControllerTest.js"></script>
</head>
<body>
</body>
</html>
and my main.js file used to load the requirejs dependencies is :
(function() {
require.config({
baseUrl: "../www/scripts",
// alias libraries paths
paths: {
'angular': '../libs/angular',
'angular-route': '../libs/angular-route',
'angular-animate':'../libs/angular-animate',
'angular-mocks':'../libs/angular-mocks',
'angularAMD': '../libs/angularAMD.min',
'Framework7':'../libs/framework7',
'UserController':'controller/UserCtrl',
'WebCallManager':'services/WebCallManager'
},
// Add angular modules that does not support AMD out of the box, put it in a shim
shim: {
'angularAMD': ['angular'],
'angular-route': ['angular'],
'angular-animate':['angular'],
'angular-mocks':['angular'],
'Framework7':{exports: 'Framework7'}
},
//kick start application
deps: ['app']
});
require(['Framework7'], function(Framework7) {
f7 = new Framework7({
modalTitle: 'Seed App',
swipePanel: 'left',
animateNavBackIcon: true
});
return {
f7: f7
};
});
})();
I have also given the entire source for my seed project here. I would much appreciate it if anyone could help me out.

You should include all the provider and services used in your controller to avoid this error
describe('Controller:UserController', function () {
var scope,controller,webcallService,$location;
beforeEach(module('app'));
beforeEach(inject(function ($controller,$rootScope,$injector,_webcallService_) {
scope = $rootScope.$new();
webcallService=_webcallService_;
$location=$injector.get('$location');
controller = $controller('UserController', { '$scope': scope });
}));
it('checks the troller name', function () {
expect(scope.name).toBe('Superhero');
});
});

The issue you are probably experiencing is that your test code runs before require+angular finishes initializing. You should write your testcode to take your use of requirejs and angularjs into account.
This will probably mean configuring your tests using require/define just like the rest of your code, and modifying the runner accordingly.
A possible solution would be a setup like the one proposed in the accepted answer here: Getting requirejs to work with Jasmine
UPDATE: also make sure to check this Does Jasmine 2.0 really not work with require.js? That basically tells you that without modifying the jasmine boot.js there is no way to postpone jasmine 2's initialization until after require is done.

Try this way:
describe('Controller:UserController', function () {
var scope,controller;
beforeEach(module('app'));
beforeEach(inject(function ($controller,$rootScope) {
scope = $rootScope.$new();
controller = $controller('UserController', { '$scope': scope });
}));
it('checks the troller name', function () {
expect(scope.name).toBe('Superhero');
});
});
I have some unit tests online with Jasmine 2.0, you may want to take a look a the code. For example this one: http://vtortola.github.io/ng-terminal-emulator/tests/spec/vtortola.ng-terminal.spec.js

I am guessing your app.js is never included.
Guessing it should be added below this:
<!-- include source files here... -->
<script data-main="main" src="framework/lib/require.js"></script>

Related

AngularJs: Implemented IIFE in using ui router

I'm trying to implement iife and this style to seperate my files in angularjs so I have config.js that will use ui.router that was implemented this way
//config.js
(function (module) {
"use strict";
module.config([
"$stateProvider","$urlRouterProvider","$locationProvider",
function ($stateProvider, $urlRouterProvider,$locationProvider) {
$urlRouterProvider.otherwise("/Views/Profile.html");
$stateProvider
.state("profile", {
url: "/",
templateUrl: "Profile.html",
controller: "profileController as vm"
})
.state("profiledetails", {
url: "ProfileDetails",
templateUrl:"ProfileDetails.html",
controller: "profileController as vm"
})
}
])
})(angular.module("appMain", ["ui.grid","ui.router","profileService"]));
and I have this profile.html which has a link to profiledetail.html
<!DOCTYPE html>
<html ng-app="appMain">
<head>
<title></title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link href="../Content/ui-grid.css" rel="stylesheet" />
<link href="../Content/bootstrap.min.css" rel="stylesheet" />
</head>
<body class="container-fluid">
<div ng-controller="profileController">
<div id="profileGrid" ui-grid="gridOptions"></div>
</div>
<script src="../scripts/angular.js"></script>
<script src="../scripts/angular-ui-router.js"></script>
<script src="../scripts/angular-resource.js"></script>
<script src="../scripts/ui-grid.min.js"></script>
<script src="../scripts/App/config.js"></script>
<script src="../scripts/App/Profile/profileService.js"></script>
<script src="../scripts/App/Profile/profileController.js"></script>
<script src="../scripts/App/helper.js"></script>
profile details
<div ui-view></div>
</body>
</html>
And this is my profilecontroller.js
(function(module) {
"use strict";
module.controller("profileController", ["$scope", "profileService", profileController]);
function profileController($scope, profileService) {
var vm = this;
var scope = $scope;
vm.profiles = getProfiles;
var onProfiles = [{
firstName: "Juan",
lastName: "Dela Cruz"
}, {
firstName: "Andres",
lastName: "Cruz"
}];
function getProfiles() {
profileService.getProfiles()
.then(onProfiles(result));
};
scope.gridOptions = {
enableSorting: true,
columnDefs: [{
name: "firstName",
field: "firstName"
}, {
name: "lastName",
field: "lastName"
}],
data: onProfiles
};
}
}(angular.module("appMain")));
In running the code and upon click to the link theres an error in chrome saying "Error: Could not resolve 'profiledetails' from state ''". Not sure if my implementation of iife caused this issue. Please someone guide me to the correct path.
You don't need to re-inject the module's dependencies when creating the profileController, and the iife parameter should immediately follow the closing curly bracket, so:
})(angular.module("appMain", ["profileService", "ui.grid","ui.router"]));
can become:
}(angular.module("appMain")));
This way you're retrieving the previously created module, rather than creating a new one. See the Creation versus Retrieval section of the docs for a note on this.
Also onProfiles is an array (not a function), so I think you need to change this:
function getProfiles() {
profileService.getProfiles()
.then(onProfiles(result));
};
To something more like this:
function getProfiles() {
profileService.getProfiles()
.then(function(result){
// do something with the "onProfiles" array here.
});
};
You use the same controller in your profile detail which is profileController
So in your html you should add
profile details
<div ui-view></div>
So that routing to profile detail can process

Angular template routing doesn't work

I'd like to load a template html in my main index.html when I view my angular project but I always get an empty screen.
<!DOCTYPE html>
<html lang="nl" ng-app="store">
<head>
<meta charset="UTF-8">
<title>NMDAD-II Web App</title>
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body class="bg-darkRed" ng-controller="StoreController as store">
<div ng-view></div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28//angular-route.min.js"></script>
<script src="vendor/angular/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="js/main.js"></script>
<script src="app/app.js"></script>
<script type="text/javascript">
angular.module("store", ["ngRoute"])
.config(function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'app/home/home.view.html'
})
.otherwise({
redirectTo: '/'
});
});
</script>
<script id="__bs_script__">//<![CDATA[
document.write("<script async src='http://HOST:3000/browser-sync/browser-sync-client.2.11.2.js'><\/script>".replace("HOST", location.hostname));
//]]></script>
</body>
</html>
I've also tried to load it with browser sync but it's still the same. I want to load home.view.html in my index.html. I tried to write the javascript in app.js but that still didn't work.
EDIT: this is my app.js. my main.js just contains some jquery
function () {
'use strict';
// Module declarations
angular.module('store', [
// Angular Module Dependencies
// ---------------------------
'ngAnimate',
'ngMaterial',
'ngMessages',
'ngResource',
// Third-party Module Dependencies
// -------------------------------
'ui.router', // Angular UI Router: https://github.com/angular-ui/ui-router/wiki
// Custom Module Dependencies
// --------------------------
'store.home',
'store.services'
]);
angular.module('store.home', []);
angular.module('store.services', []);
// Make wrapper services and remove globals for Third-party Libraries
angular.module('store')
.run(Run);
function Run(
$_,
$faker
) {}
var app = angular.module('store',[]);
app.controller('StoreController', function(){
this.products = gems;
});
var gems = [
{
title: "Islay Blended Malt",
description: "The Isle of Islay is known for its peaty whiskies. For there is a great abundance of peat on the island, and because electricity reached Islay so late, peated was relied upon as a staple source of fuel. But there is so much than just peat to be found.",
price: "103.45",
canPurchase: true
},
{
title: "Springbank 10 Year old",
description: "Blended from a mixture of bourbon and sherry casks, the light colour of this malt belies the richness of its character.",
price: "36.25",
canPurchase: true
},
{
title: "Hazelburn 10 Year old",
description: "First released in 2014, this is the first bottling of Hazelburn at 10 years of age. Hazelburn is Springbank's triple-distilled, unpeated single malt.",
price: "37.75",
canPurchase: true
}
]
})();
The problem I see is you are loading angular-route before you load angular.
Try switching those two lines to:
<script src="vendor/angular/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28//angular-route.min.js"></script>
I get this error ReferenceError: angular is not defined when I load the scripts how you are loading them.

Keep getting AngularJS module not available (ASP.NET 5)

Trying to get simple Angular DI working in an existing ASP.NET 5 (Core) project.
Been following this tutorial.
Versions:
AngularJS 1.4.6
ASP.NET 5 (vNext)
Visual Studio 2015
Windows 10
Checked all the basic gotchas with naming and so on. Unclear about how my dependent js-files "controllers.js" & "services.js" are suppose to be discovered by Angular?
If I explicitly include them - which by the tutorial shouldn't be required - I still get
[ng:areq] Argument 'customerController' is not a function, got
undefined
Index.html
<!DOCTYPE html>
<html ng-app="bonusapp">
<head>
<meta charset="utf-8" />
<link href="lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="lib/bootswatch/yeti/bootstrap.min.css" rel="stylesheet" />
<link href="css/main.css" rel="stylesheet" />
<script type="text/javascript" src="lib/angular/angular.js"></script>
<script type="text/javascript" src="lib/angular-resource/angular-resource.js"></script>
<script type="text/javascript" src="lib/angular-route/angular-route.js"></script>
<script src="lib/app.js"></script>
<!--<script>angular.bootstrap(document, ['app']);</script>-->
</head>
<body ng-cloak>
<div id="wrapper" ng-controller="customerController">
<div id="main" class="container-fluid">
<div class="row">
<div class="col-md-3">
<h2>Kunder</h2>
<ul>
<li ng-repeat="item in Models">
{{item.FirstName}} {{item.LastName}} <a>Redigera</a> <a>Radera</a>
</li>
</ul>
</div>
</div>
</div>
<script type="text/javascript" src="lib/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="lib/bootstrap/dist/js/bootstrap.min.js"></script>
<script type="text/javascript" src="lib/jquery-validation/dist/jquery.validate.js"></script>
<script type="text/javascript" src="lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</body>
</html>
app.js
(function () {
'use strict';
// Define module "app"
angular.module('bonusapp', [
// Angular modules
'ngRoute',
'ngResource',
// Custom modules
'customerService'
// 3rd Party Modules
]);
})();
controllers.js
(function () {
'use strict';
// Assign controller to app
angular
.module('bonusapp')
.controller('customerController', [
customerController]);
// $inject() method call is required to enable the controller to work with minification.
customerController.$inject = [
'$scope',
'Customers'
];
// Construct controller
function customerController($scope, Customers) {
// Populate model from service
$scope.Models = Customers.get();
}
})();
services.js
(function() {
'use strict';
var customerService =
angular
.module('customerService', ['ngResource']);
customerService
.factory('Customers',
['$resource'],
function ($resource) {
return $resource('/api/customers', {}, {
// Service call to get Customers
get: {
method: 'GET',
params: {},
isArray: true
}
});
}
);
})();
As Win suggested, I needed to:
Fix the include order to put jQuery first
Include all my JS files
But I still had some issues. For reference, here are the fixed scripts:
controller.js
(function () {
'use strict';
// Construct controller
// Remarks: controller is now declared FIRST
var customerController = function ($scope, Customers) {
$scope.Title = "Title";
// Populate model from service
$scope.Models = Customers.get();
}
// $inject() method call is required to enable the controller to work with minification.
customerController.$inject = [
'$scope',
'Customers'
];
// Assign controller to app
angular
.module('bonusapp')
.controller('customerController',
customerController);
})();
services.js
(function() {
'use strict';
var customerService =
angular
.module('customerService',
['ngResource']);
customerService
.factory('Customers',
['$resource',
function ($resource) {
return $resource('/api/customers', {}, {
// Service call to get Customers
// Remarks: 'get' in single quotes
'get': {
method: 'GET',
params: {},
isArray: true
}
});
}
]);
})();
You need to include controller.js and services.js files.
In addition, you need to move jquery before angular.js.
<script type="text/javascript" src="lib/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="lib/angular/angular.js"></script>
<script type="text/javascript" src="lib/angular-resource/angular-resource.js"></script>
<script type="text/javascript" src="lib/angular-route/angular-route.js"></script>
<script src="lib/app.js"></script>
<script src="lib/controllers.js"></script>
<script src="lib/services.js"></script>
FYI: You might also want to look into bundling and magnification, before you publish.

How to have controllers in separate file in AngularJS

I look around a bit and didn't find an answer that fit with my current situation. I have a app.js file:
'use strict';
var demoApp = angular.module('demoApp', [
// Dépendances du "module" <-- demoApp
'ngRoute',
'routeAppControllers',
'todoList'
]);
demoApp.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
// Système de routage
$routeProvider
.when('/home', {
templateUrl: 'views/home.html',
controller: 'homeCtrl'
})
.when('/contact/:msg?', {
templateUrl: 'views/contact.html',
controller: 'contactCtrl'
})
.when('/todolist', {
templateUrl: 'views/todolist.html',
controller: 'listeCtrl'
})
.when('/testfiltre', {
templateUrl: 'views/testfiltre.html',
controller: 'demoFiltreCtrl'
})
.when('/testCreationfiltre', {
templateUrl: 'views/testcreationfiltre.html',
controller: 'demoCreationFiltreCtrl'
})
.otherwise({
redirectTo: '/home'
});
}
]);
var routeAppControllers = angular.module('routeAppControllers', []);
routeAppControllers.controller('homeCtrl', ['$scope',
function($scope){
$scope.message = "Bienvenue sur la page d'accueil";
}
]);
routeAppControllers.controller('contactCtrl', ['$scope','$routeParams',
function($scope, $routeParams){
$scope.message = "Laissez-nous un message sur la page de contact !";
$scope.msg = $routeParams.msg || "Bonne chance pour cette nouvelle appli !";
}
]);
routeAppControllers.controller('listeCtrl', [function(){}]);
I have todolist module in todolist_controller.js:
var todoList=angular.module('todoList',[]);
todoList.controller('todoCtrl', ['$scope',
function ($scope) {
var todos = $scope.todos = [];
$scope.addTodo = function () {
var newTodo = $scope.newTodo.trim();
if (!newTodo.length) {
return;
}
todos.push({
title: newTodo,
completed: false
});
$scope.newTodo = '';
};
$scope.removeTodo = function (todo) {
todos.splice(todos.indexOf(todo), 1);
};
$scope.markAll = function (completed) {
todos.forEach(function (todo) {
todo.completed = completed;
});
};
$scope.clearCompletedTodos = function () {
$scope.todos = todos = todos.filter(function (todo) {
return !todo.completed;
});
};
}
]);
I have my index.html page:
<!DOCTYPE html>
<html lang="fr" ng-app="demoApp">
<head>
<meta charset="utf-8" />
<title>Demo App</title>
<link rel="stylesheet" href="styles/style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular-route.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-i18n/1.4.2/angular-locale_fr-ca.min.js"></script>
<script src="scripts/controllers/app.js"></script>
<script src="scripts/controllers/todolist_controllers.js"></script>
</head>
<body>
<div ng-view>
</div>
<nav>
Page d'accueil
Page de contact
Todo list
test filtre
test création filtre
</nav>
</body>
</html>
I read that I'm suppose to call, for example, my main module App and all my other module file should start with: angular.module('App').controller(...
But, this would imply that if I change the name of my app from 'app' to 'my_app' for example, I would have to go trough all my controllers and change 'app' for 'my-app'.
I would like to avoid that and just be able to import my file in index.html and just have to declare it in the dependencies of my 'app' module.
Angular Structure
When you build an angular app you should separate as much as possible to give your code readability. You should create a module for each page/part of your web app.
Example
Here is an example of this type of structure, I wrote this and use it as a base for angular apps.
app folder
This folder holds all of your components and routes.
routes.js
This file has the states of your project and is its own module
app.js
This file is just the base where you can call all your other modules as dependencies.
var app = angular.module("myApp", [
'ui.bootstrap',
'ngAnimate',
'myAppRouter',
'myAppHomeCtrl',
'myAppHomeService',
'myAppNavbarDirective',
'myAppNavbarService',
'myAppLoginCtrl',
'myAppLoginService'
]);
You can see all of the different modules written and added here. See the way this is called myApp? well we call that part in the html
<html ng-app="myApp">
components
this will contain things like "home" and "contact" these folders should have everything then need in little self contained html, controllers and services.
controller/module
This is the bit that really answers your question, to add a new module for a controller you do as follows.
angular.module('myAppHomeCtrl', []).controller('homeCtrl', ['$scope', 'homeContent', function($scope, homeContent){
$scope.dataset = homeContent.getContent();
$scope.header = homeContent.getHeader();
$scope.subheading = homeContent.getSubheader();
}]);
service/factory
So you can see that in the module we call a factory, this is also in this folder and looks like this.
angular.module('myAppHomeService', [])
.factory('homeContent', function(){
return {
getHeader: function(){
return "Welcome Human";
},
getSubheader: function(){
return "To Joe's Awesome Website";
},
};
});
Back to index.html
So back in our index we can add all of these modules in <script> tags like this.
<!-- Angular Modules -->
<script type="text/javascript" src="app/app.module.js"></script>
<script type="text/javascript" src="app/app.routes.js"></script>
<script type="text/javascript" src="app/components/home/homeCtrl.js"></script>
<script type="text/javascript" src="app/components/home/homeService.js"></script>
<script type="text/javascript" src="app/shared/navigation-bar/navbarDirective.js"></script>
<script type="text/javascript" src="app/shared/navigation-bar/navbarService.js"></script>
<script type="text/javascript" src="app/components/login/loginCtrl.js"></script>
<script type="text/javascript" src="app/components/login/loginService.js"></script>
In production you will minify all these but you can just call them alll like this whilst in dev.
Conclusion
To conclude I'll do a summery to make sure you have everything you need to get your modules to work
go to your app.js (main angular module) and app the name to it.
go to your components and create the new module
go to the index.html and add your script tag that links to the new module
now you can use the controllers and all the components as you wish
I hope this guid to angular structure helps you. Good Luck
instead of defining the app as var app = angular.module('myApp', []); use angular.module('myApp', []); var not necessary. Then in separate files like somethingCtrl.js you can define controllers like:
angular.module('myApp')
.controller('somethingCtrl', ['$scope', function ($scope) {
}]);`
then you can add the script tags in order on html. start with the module definition first. Use these style guidelines for angular
OPTION 2
define your first module. Then you define various other modules and use them as dependencies like so
index.js:
angular.module('mainApp', ['otherApp']);
other.js
angular.module('otherApp', []);
This gives you the flexibility to add all of your controllers to one module and all of your directives to another. You can mix the functionality around by using modules as dependencies. Just make sure the mainApp is loaded first in the script tag order.
This is where requirejs or browserify would help you enormously. However as your question doesn't relate to either of them you can use good ol' JS to accomplish something similar.
Take for example your app.js file. Build in a global config object, then use that when referencing the app name wherever you are. Then it's a case of just changing the app name in the config object to something else without breaking any other components.
var config = {
app : "myApp"
}
angular.module(config.app, ["ngAnimate"]);
Now a controller in controller.js can use that same config object.
angular.module(config.app)
.controller("myController", function($scope) { ... }
As long as you load in app.js first you'll have the config object available.
<script src="/js/app.js"></script>
<script src="/js/controller.js"></script>
This isn't pretty and I'd advise you to use browserify or requirejs (or any other alternative) in the future to build out your front end if you want this kind of functionality without the need for horrible global objects/variables.
Say this is your directory layout:
├── controllers
│   └── home.js
├── directives
└── index.html
You define your controller in home.js like you usually would, and then include it in index.html with:
...
<script src="./controllers/home.js"></script>
...
P.S.: Using the script tag should be the preferred way to do this, however should you wish to use Require.js, there is a fantastic library angularAMD

AngularJS Error: $injector:unpr Unknown Provider

I'm trying to build my own service by following the example in the documentation for the factory methodology. I think I've done something wrong however because I continue to get the unknown provider error. This is my code for my app including the declaration, configuration and factory definition.
EDIT
I've now added all of the files to help troubleshoot
EDIT
The full details of the error are below the issues appears to be with getSettings, as it's looking for getSettingsProvider and cannot find it
Error: [$injector:unpr] http://errors.angularjs.org/1.2.16/$injector/unpr? p0=getSettingsProvider%20%3C-%20getSettings
at Error (native)
at http://localhost/sw/selfservice/bower_components/angular/angular.min.js:6:450
at http://localhost/sw/selfservice/bower_components/angular/angular.min.js:35:431
at Object.c [as get] (http://localhost/sw/selfservice/bower_components/angular/angular.min.js:34:13)
at http://localhost/sw/selfservice/bower_components/angular/angular.min.js:35:499
at c (http://localhost/sw/selfservice/bower_components/angular/angular.min.js:34:13)
at d (http://localhost/sw/selfservice/bower_components/angular/angular.min.js:34:230)
at Object.instantiate (http://localhost/sw/selfservice/bower_components/angular/angular.min.js:34:394)
at http://localhost/sw/selfservice/bower_components/angular/angular.min.js:66:112
at http://localhost/sw/selfservice/bower_components/angular/angular.min.js:53:14 angular.js:9778
(anonymous function) angular.js:9778
(anonymous function) angular.js:7216
h.$apply angular.js:12512
(anonymous function) angular.js:1382
d angular.js:3869
$b.c angular.js:1380
$b angular.js:1394
Wc angular.js:1307
(anonymous function) angular.js:21459
a angular.js:2509
(anonymous function) angular.js:2780
q angular.js:330
c
These are all of the files I have in my app currently
app.JS
//Initialize angular module include route dependencies
var app = angular.module("selfservice", ['ngRoute']);
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl:"partials/login.html",
controller:"login"
});
});
app.factory('getSettings', ['$http', '$q', function($http, $q) {
return function (type) {
var q = $q.defer();
$http.get('models/settings.json').success(function (data) {
q.resolve(function() {
var settings = jQuery.parseJSON(data);
return settings[type];
});
});
return q.promise;
};
}]);
And here is how I am using this service in my controller
controller.JS
app.controller("globalControl", ['$scope','getSettings', function ($scope,getSettings) {
var loadSettings = getSettings('global');
loadSettings.then(function(val) {
$scope.settings = val;
});
}]);
app.controller("login", ['$scope', function ($scope) {
return ""
}]);
directives.js
app.directive('watchResize', function(){
return {
restrict: 'M',
link: function(scope, elem, attr) {
scope.spacer = (window.innerWidth < 1025) ? '' : 'large-3';
scope.button = (window.innerWidth < 1025) ? '' : 'large-6';
angular.element(window).on('resize', function(){
scope.$apply(function(){
scope.spacer = (window.innerWidth < 1025) ? '' : 'large-3';
scope.button = (window.innerWidth < 1025) ? '' : 'large-6';
});
});
}
};
});
And if it's pertinent here's the HTML
<html class="no-js" lang="en" ng-app="selfservice" ng-controller="globalControl">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{settings.title}}</title>
<link rel="stylesheet" href="css/app.css" />
<script src="bower_components/modernizr/modernizr.js"></script>
<script src="bower_components/angular/angular.min.js"></script>
<script src="bower_components/angular-route/angular-route.min.js"></script>
<script src="bower_components/jquery/dist/jquery.min.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/directives.js"></script>
</head>
<body>
<div id="template">
<header id="header">
<img src="{{settings.logo}}" alt="{{settings.logoDescription}}"/>
</header>
<div id="view">
<ng-view></ng-view>
</div>
</div>
<script src="bower_components/foundation/js/foundation.min.js"></script>
<script>
//initialize foundation
$(document).foundation();
</script>
</body>
</html>
Can someone point me in the right direction? I have done my best to follow the documentation, and looking through SO most of the related issues are much more in depth, and more difficult for me to understand. This is my first time creating a service.
also one of the popular reasons maybe you miss to include the service file in your page
<script src="myservice.js"></script>
Your angular module needs to be initialized properly. The global object app needs to be defined and initialized correctly to inject the service.
Please see below sample code for reference:
app.js
var app = angular.module('SampleApp',['ngRoute']); //You can inject the dependencies within the square bracket
app.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl:"partials/login.html",
controller:"login"
});
$locationProvider
.html5Mode(true);
}]);
app.factory('getSettings', ['$http', '$q', function($http, $q) {
return {
//Code edited to create a function as when you require service it returns object by default so you can't return function directly. That's what understand...
getSetting: function (type) {
var q = $q.defer();
$http.get('models/settings.json').success(function (data) {
q.resolve(function() {
var settings = jQuery.parseJSON(data);
return settings[type];
});
});
return q.promise;
}
}
}]);
app.controller("globalControl", ['$scope','getSettings', function ($scope,getSettings) {
//Modified the function call for updated service
var loadSettings = getSettings.getSetting('global');
loadSettings.then(function(val) {
$scope.settings = val;
});
}]);
Sample HTML code should be like this:
<!DOCTYPE html>
<html>
<head lang="en">
<title>Sample Application</title>
</head>
<body ng-app="SampleApp" ng-controller="globalControl">
<div>
Your UI elements go here
</div>
<script src="app.js"></script>
</body>
</html>
Please note that the controller is not binding to an HTML tag but to the body tag. Also, please try to include your custom scripts at end of the HTML page as this is a standard practice to follow for performance reasons.
I hope this will solve your basic injection issue.
app.factory('getSettings', ['$http','$q' /*here!!!*/,function($http, $q) {
you need to declare ALL your dependencies OR none and you forgot to declare $q .
edit:
controller.js : login, dont return ""
This error is also appears when one accidntally injects $scope into theirs factory:
angular.module('m', [])
.factory('util', function ($scope) { // <-- this '$scope' gives 'Unknown provider' when one attempts to inject 'util'
// ...
});
Spent a few hours trying to solve the same. This is how I did it:
app.js:
var myApp = angular.module( 'myApp', ['ngRoute', 'ngResource', 'CustomServices'] );
CustomServices is a new module I created and placed in a separate file called services.js
_Layout.cshtml:
<script src="~/Scripts/app.js"></script>
<script src="~/Scripts/services/services.js"></script>
services.js:
var app = angular.module('CustomServices', []);
app.factory( 'GetPeopleList', ['$http', '$log','$q', function ( $http, $log, $q )
{
//Your code here
}
app.js
myApp.controller( 'mainController', ['$scope', '$http', '$route', '$routeParams', '$location', 'GetPeopleList', function ( $scope, $http, $route, $routeParams, $location, GetPeopleList )
You have to bind your service to your new module in the services.js file AND of course you have to use that new module in the creation of your main app module (app.js) AND also declare the use of the service in the controller you want to use it in.
I was getting this problem and it turned out I had included my controller both in ui.router and in the html template as in
.config(['$stateProvider',
function($stateProvider) {
$stateProvider.state('dashboard', {
url: '/dashboard',
templateUrl: 'dashboard/views/index.html',
controller: 'DashboardController'
});
}
]);
and
<section data-ng-controller="DashboardController">
Please "include" both Controller and the module(s) where the controller and the functions called in the Controller are.
module(theModule);
# user2310334
I just tried this, a VERY basic example:
HTML file
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular-route.min.js" type="text/javascript"></script>
<script src="./app.js" type="text/javascript"></script>
</head>
<body>
<div ng-controller="MailDetailCtrl">
</div>
</body>
</html>
The javascript file:
var myApp= angular.module('app', ['ngRoute']);
myApp.factory('mailService' , function () {
return {
getData : function(){
var employees = [{name: 'John Doe', id: '1'},
{name: 'Mary Homes', id: '2'},
{name: 'Chris Karl', id: '3'}
];
return employees;
}
};
});
myApp.controller('MailDetailCtrl',['$scope', 'mailService', function($scope, mailService) {
alert(mailService.getData()[0].name);
}]);
And it works. Try it.
Be sure that you load controller outsideapp.config. The following code may cause this error:
app.config(["$stateProvider", "$urlRouterProvider", function ($stateProvider, $urlRouterProvider) {
var AuthCtrl = require('components/auth/AuthCtrl'); //NOTICE HERE
$stateProvider.state('login',{
url: "/users/login",
templateUrl: require("components/auth/login.tpl.html"),
controller: AuthCtrl // ERROR
})
}))
To fix this error, we must move AuthCtrl to outsideapp.config:
var AuthCtrl = require('components/auth/AuthCtrl'); //NOTICE HERE
app.config(["$stateProvider", "$urlRouterProvider", function ($stateProvider, $urlRouterProvider) {
$stateProvider.state('login',{
url: "/users/login",
templateUrl: require("components/auth/login.tpl.html"),
controller: AuthCtrl // WORK
});
}))
In my case, I added a new service (file) to my app. That new service is injected in an existing controller. I did not miss new service dependency injection into that existing controller and did not declare my app module no more than one place. The same exception is thrown when I re-run my web app and my browser cache is not reset with a new service file codes. I simply refreshed my browser to get that new service file for browser cache, and the problem was gone.
Since this is the first Stackoverflow question that appears on Google when searching for Error: $injector:unpr Unknown Provider I'll add this here.
Make sure that in your index.html any modules/dependencies are not being loaded after they are needed.
For example in my code customFactory.factory.js begins like this:
angular
.module("app.module1")
.factory("customFactory", customFactory);
However the index.html looked like this:
<script src="/src/client/app/customFactory.factory.js"></script>
<script src="/src/client/app/module1.module.js"></script>
Where it should've really looked like this:
<script src="/src/client/app/module1.module.js"></script>
<script src="/src/client/app/customFactory.factory.js"></script>
Since customFactory.factory.js is declared as part of module1, it needs to be loaded before customFactory
I got this error writing a Jasmine unit test. I had the line:
angular.injector(['myModule'])
It needed to be:
angular.injector(['ng', 'myModule'])
When you are using ui-router, you should not use ng-controller anywhere. Your controllers are automatically instantiated for a ui-view when their appropriate states are activated.

Categories

Resources