How to have controllers in separate file in AngularJS - javascript

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

Related

Mapping AngularJs component in routing when() method

I am trying to create my first AngularJS app.
But I can not understand why my routing is not working properly(i think there is some problem in my when() method and directory structure).
Here is my directory structure(I have followed AngularJS standard naming convention).
Directoty Structure
-Home
--sidebar
---sidebar.component
---sidebar.template
--home.component
--home.template
--home.module
-menu
--menu.module
--menu-list
---menu-list.component
---menu-list.template
-app.js
app.js
angular.module('myApp', [
'ngRoute',
'menu',
'home'
]).
config(['$locationProvider', '$routeProvider', function($locationProvider, $routeProvider) {
$locationProvider.hashPrefix('!');
$routeProvider
.when('/menu-list', {
template: '<menu-list></menu-list>'
})
.when('/home', {
template: '<home></home>'
})
.when('/sidebar', {
template: '<sidebar></sidebar>'
})
.otherwise('/home');
}]);
menu.module.js
angular.module('menu',[]);
menu-list.component.js
angular.module('menu')
.component('menu-list', {
templateUrl: 'menu/menu-list/menu-list.html',
controller: [
function MenuListController() {
alert("MenuListController Called");
}
]
});
Been a long time since I've tried using ngRoute but here's how my 'otherwise' statement differs from yours:
.otherwise({
redirectTo: '/home'
});
The difference is here I pass in an object with the property 'redirectTo'. You can check this article out as well.
The Problem was I did not name component correctly. In angularJS to include the view in html we need to name component in camelCase and it will be included by hyphen-case
Component name: 'phoneList'
View name: '<phone-list></phone-list>'
Example from AngularJS-Tutorial
app/index.html:
<html ng-app="phonecatApp">
<head>
...
<script src="bower_components/angular/angular.js"></script>
<script src="app.js"></script>
<script src="phone-list.component.js"></script>
</head>
<body>
<!-- Use a custom component to render a list of phones -->
<phone-list></phone-list>
</body>
</html>
app/phone-list.component.js:
// Register `phoneList` component, along with its associated controller and template
angular.
module('phonecatApp').
component('phoneList', {
template:'phone-list.html',
controller: function PhoneListController() {
//...
}
});
Note:If any error or written badly feel free to Edit

Why can't I use AngularJS to load a JSON file and angular route in the same page?

I'm not a native speaker, sorry for my unclear question.
I'm trying to use AngularJS to read a JSON file. I did it but when I use angular route in the same page, the angular route didn't run. Then I figured out that I can only use one function in 1 page. For more clearly, here is my code:
In home.html:
<!DOCTYPE html>
<html ng-app="UpStore">
<head>
</head>
<body ng-controller="ProductController">
<div ng-view> </div>
<!--Javascript-->
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js">
</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-
route.js"></script>
<script src="js/app.js"></script>
<script>
var app = angular.module("UpStore", [])
app.controller("ProductController", function ($scope, $http) {
$http({
method: "GET",
url: "productdata.json"
}).then(function mySucces(respone) {
$scope.products = respone.data
}, function myError(respone) {
$scope.dataError = respone.statusText
}
)
})
</script>
</body>
</html>
app.js:
var App = angular.module('UpStore', []);
App.controller('ProductController', function ($scope) {
});
var App = angular.module('UpStore', ['ngRoute']);
App.config(function ($routeProvider) {
$routeProvider
.when('/men', {
templateUrl: 'men.html',
})
.when('/product', {
templateUrl: 'product.html',
}).
otherwise({
redirectTo: 'men'
});
});
App.controller('ProductController', function ($scope) {
});
In men.html:
<div ng-repeat="pd in products">
<p>{{pd.ID}}</p>
<p><img src="image/{{pd.Image}}" /></p>
</div>
I also has one more question. In page men.html, I have several products, each product has an ID. I have a page product.html to show the product details. What I want to do is when I click on an image of a product in page men.html. The URL to the product.html would be like product.html/productid. I know that $routeParams can solve my problem, but I don't know how to write the code.
I really need some help because I've been struggling with these 2 problems for hours. Thanks in advance.
You are continuously overwriting the previously defined modules.
As you have already defined the module UpStore in the app.js
//Define it only once
var App = angular.module('UpStore', ['ngRoute']);
You need to get the reference of it in the script block and use.
//Get the reference to existing module
var app = angular.module("UpStore");
//Use it
app.controller(.......)
Additionally: Note always use same version of angular.js and angular-route.js library

Template not loading under component design

I am trying to make a single page application while using components since my company will be moving to using components in the future and I am trying to follow the angular-phonecat tutorial. The problem I'm having is that for some reason in my app.config.js file, the template for the home page is not being recognized (the home-page portion) and I can't figure out why. If I replace that with a simple string of 'hello', it displays just fine, so it has to be somewhere in my components but I can't track down why it's not recognizing it.
Relevant code:
app.config.js:
angular.
module('newSpa').
config(['$locationProvider', '$routeProvider',
function config($locationProvider, $routeProvider){
$locationProvider.hashPrefix('!');
$routeProvider.
when('/home',{
template: '<home-page></home-page>'
}).
when('/contacts', {
template:'<contacts></contacts>'
}).
otherwise('/home');
}]);
app.module.js:
angular.module('newSpa', [
'ngRoute',
'homePage',
'contacts'
]);
home-page.template.html:
<div>
<p>{{message}}</p>
</div>
home-page.module.js:
angular.module('homePage', []);
home-page.component.js:
angular.module('homePage').component('homePage', {
templateUrl: 'home-page/home-page.template.html',
controller: 'homeCtrl'
});
controllers.js:
angular.module('homePage', []).controller('homeCtrl', ['$scope', function($scope){
$scope.message = 'hello';
}]);
index.html:
<!DOCTYPE html>
<html lang="en" ng-app="newSpa">
<head>
<meta charset="UTF-8">
<title>SPA Contacts</title>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="app.module.js"></script>
<script src="app.config.js"></script>
<script src="home-page/home.module.js"></script>
<script src="home-page/home.component.js"></script>
<script src="contacts/contacts.module.js"></script>
<script src="contacts/contacts.component.js"></script>
<script src="controllers/controllers.js"></script>
</head>
<body>
<div ng-view></div>
</body>
</html>
My app.config.js file is in the root "app" directory, and my home files are all in the "/app/home-page" directory. Link to angular-phonecat: https://docs.angularjs.org/tutorial/step_03
So my previous solution was still incorrect. The real solution is that my controller was redefining the 'home' module because I had square brackets. Here is the old controller:
angular.module('homePage', []).controller('homeCtrl', ['$scope', function($scope){
$scope.message = 'hello';
}]);
So as you can see, when I have square brackets in the module definition, I am redefining the module, thereby overwriting all previous definitions of the module. When I removed those brackets:
angular.module('homePage').controller('homeCtrl', ['$scope', function($scope){
$scope.message = 'hello';
}]);
Everything displays properly. So the issue was I was making a new module with just the controller, so it didn't have the template to push to the view to update.
You seem to have named your component 'home' but are using 'home-page' in your template.

$compile:tpload Failed to load template (HTTP status: 404) happens in one sub url only

I am trying to run my angularjs-based app on local file throughout File transfer protocol(not on any server).
My project contains html files as
index.html and template folder on the top level, and other sub html files, such as common.html, main.html, etc. which are included in the template folder.
This app triggers the error below,
Error: [$compile:tpload] Failed to load template: template/common.html (HTTP status: 404),
only when entering through File transfer, file:///C:/Webapp/index.html#common/abc.
But it does not happen when entering by http.
Also, this file transfer access triggers an error in Chrome, IE, but not in Firefox.
And the second odd thing is that this happens only when url ends with #common/abc.
The only one url that triggers the tpload error goes like
file:///C:/Webapp/index.html#common/abc (case only with #common/~ after index.html, and I don't get the error if it doesn't has 'abc' at the last).
The 'abc' functions like parameters(called channelTag on my project) going to be input on my App, not actual files.
And This project intends to start with the url file:///C:/Webapp/index.html#common/abc which gets the channelTag, and flows
other sub urls.
Other urls like file:///C:/Webapp/index.html#main, or file:///C:/Webapp/index.html#sub2 are okay. No errors are shown there.
After checking some related answers on searching,
most of the answers say to include bootstrap-tpls.js instead of bootstrap.js, but this method shows the same result.
Attached are the html and javascript code below :
index.html:
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="EUC-KR">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="{{metaservice.metaViewport()}}" />
<title>BtvWebApp</title>
<link rel="stylesheet" type="text/css" href="css/btv.css">
<script src="js/lib/jquery-1.11.1.min.js"></script>
<script src="js/bxslider/jquery.bxslider.min.js"></script>
<script src="js/lib/angular.js"></script>
<script src="js/bootstrap/bootstrap.js"></script>
<script src="js/lib/angular-route.min.js"></script>
<script src="js/lib/angular-sanitize.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular-resource.min.js"></script>
<script src="js/app.js"></script>
<script src="js/lib/script.js"></script>
<script src="js/view/main/mainController.js"></script>
<script src="js/view/commonController.js"></script>
<script src="js/filters/zerofillFilter.js"></script>
<script src="js/config/constants.js"></script>
<script src="js/config/messages.js"></script>
</head>
<body>
<ng-view></ng-view>
</body>
</html>
common.html is an empty html file.
app.js:
var app = angular.module('myApp', [
'ngRoute',
'ngSanitize',
'myApp.constant',
'myApp.messages'
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/main', {
templateUrl: 'template/main.html',
controller: 'mainCtrl'
})
// Containing other sub whens...
/////////////////////////////
.otherwise({redirectTo: '/common/:channelTag'});
}]);
commonController.js:
'use strict';
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/common/:channelTag', {
templateUrl: 'template/common.html',
controller: 'commonCtrl'
});
}])
.controller('commonCtrl', ['$scope', '$location', '$http', '$rootScope', '$routeParams', 'commonConstant', 'information', 'Utils', 'MetaService'
, function($scope, $location, $http, $rootScope, $routeParams, commonConstant, information, Utils, MetaService) {
$scope.isDataLoading = true;
var channelTag = $routeParams.channelTag;
if(!Utils.isEmpty(channelTag)){
information.channelTag = channelTag;
}
}])
.service('MetaService', function() {
var metaViewport = '';
return {
set: function(newViewport) {
metaViewport = newViewport;
},
metaViewport: function() { return metaViewport; }
}
});
What is the problem when running through file transfer protocol even I set the chrome option with disable-security?
And why I get the error only when the url ends with '~#common/abc' ?
Any suggestions are welcome, please.
Including ui.bootstrap.tpls in your project will fix above issue
Oops, I solved this problem myself.
It was due to common.html with empty code, so some browsers could not find the template contents. Adding a <div> tag in that file, no error found.
Wish it be helping someone...

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