I am working with blade template engine. I want to follow a convention of "One Controller per Page" to easily handle code.
I have one JS file which has few controllers which will be used in all files/pages So i included in my template file which will automatically generated in each page.
Code is as follows
angular.module('MyApp',['angularFileUpload'])
.factory('MyFactory', ['$http',function($http) {
return{
get: function(callback){
$http.get('my-url')
.success(function(data) {
callback(data);
});
}
};
}])
.controller('GlobalController',['$scope','$http','MyFactory',function($scope,$http,MyFactory){
SchoolFactory.get(function(data){
console.log(data);
});
// Few Function which will be called in all pages
}]);
Now When create a new page using that template that includes above JS, I get error. Here is what I create new js file.
angular.module('MyApp',[])
.controller('SomeController',['$scope','$http',function($scope,$http){
// Few Function which will be called in all pages
}]);
Any Page which include this module i get error in console that SomeController is not a function.
Please help me. Thanks in advance.
This is same problem which i faced when i started working with Angular JS. Your code has very little error.
You can create multiple angular.module in single page but only one can have dependencies.
angular.module('MyApp',['angularFileUpload'])
angular.module('MyApp')
From your second module remove empty array [].
angular.module('MyApp')
.controller('SomeController',['$scope','$http',function($scope,$http){
// Few Function which will be called in all pages
}]);
Remove the , [] in the module. Any time you pass an array to the module function, it recreates the module. Since you want to add something to an existing module, leave it off.
Is there a way to inject a late dependency to an already bootstrapped angular module? Here's what I mean:
Say that I have a site-wide angular app, defined as:
// in app.js
var App = angular.module("App", []);
And in every page:
<html ng-app="App">
Later on, I'm reopening the app to add logic based on the needs of the current page:
// in reports.js
var App = angular.module("App")
App.controller("ReportsController", ['$scope', function($scope) {
// .. reports controller code
}])
Now, say that one of those on-demand bits of logic also requires their own dependencies (like ngTouch, ngAnimate, ngResource, etc). How can I attach them to the base App? This doesn't seem to work:
// in reports.js
var App = angular.module("App", ['ui.event', 'ngResource']); // <-- raise error when App was already bootstrapped
I realize I can do everything in advance, i.e -
// in app.js
var App = angular.module("App", ['ui.event', 'ngResource', 'ngAnimate', ...]);
Or define every module on its own and then inject everything into the main app (see here for more):
// in reports.js
angular.module("Reports", ['ui.event', 'ngResource'])
.controller("ReportsController", ['$scope', function($scope) {
// .. reports controller code
}])
// in home.js
angular.module("Home", ['ngAnimate'])
.controller("HomeController", ['$scope', '$http', function($scope, $http){
// ...
}])
// in app.js, loaded last into the page (different for every page that varies in dependencies)
var App = angular.module("App", ['Reports', 'Home'])
But this will require I initialize the App everytime with the current page's dependencies.
I prefer to include the basic app.js in every page and simply introduce the required extensions to each page (reports.js, home.js, etc), without having to revise the bootstrapping logic everytime I add or remove something.
Is there a way to introduce dependencies when the App is already bootstrapped? What is considered the idiomatic way (or ways) to do this? I'm leaning towards the latter solution, but wanted to see if the way I described could also be done. thanks.
I solved it like this:
reference the app again:
var app = angular.module('app');
then push your new requirements to the requirements array:
app.requires.push('newDependency');
Simple...
Get an instance of the module using the getter like this:
var app = angular.module("App");
Then add to the "requires" collection like this:
app.requires[app.requires.length] = "ngResource";
Anyway, this worked for me. GOOD LUCK!
According to this proposal on the Angular JS google group this functionality does not exist as of this moment. Hopefully the core team decides to add this functionality, could use it myself.
If you wish to add multiple dependencies at once, you can pass them in push as follows:
<script>
var app = angular.module('appName');
app.requires.push('dependencyCtrl1', 'dependencyService1');
</script>
I realize that this is an old question, however, no working answer has yet been provided, so I decided to share how I solved it.
The solution requires forking Angular, so you can't use CDN anymore. However the modification is very small, so I am surprised why this feature doesn't exist in Angular.
I followed the link to google groups that was provided in one of the other answers to this question. There I found the following code, which solved the issue:
instanceInjector.loadNewModules = function (mods) {
forEach(loadModules(mods), function(fn) { instanceInjector.invoke(fn || noop); });
};
When I added this code to line 4414 in the angular 1.5.0 source code (inside the createInjector function, before the return instanceInjector; statement), it enabled me to add dependencies after bootstrapping like this $injector.loadNewModules(['ngCookies']);.
Since version 1.6.7 it is now possible to lazy load modules after the app has been bootstrapped using $injector.loadNewModules([modules]). Below is an example taken from AngularJS documentation:
app.factory('loadModule', function($injector) {
return function loadModule(moduleName, bundleUrl) {
return getScript(bundleUrl).then(function() { $injector.loadNewModules([moduleName]); });
};
})
Please read full documentation about loadNewModules as there are some gotchas around it.
There's also a very good sample app by omkadiri using it with ui-router.
I am new to Meteor and AngularJs. I am trying to follow the example app on https://github.com/lvbreda/Meteor_angularjs but I have not been able to get it working so far.
I am getting an error 'app is not defined' in this piece of code:
app.controller('MeteorCtrl', ['$scope', '$meteor', function ($scope, $meteor) {
Uncaught ReferenceError: app is not defined
$scope.todos = $meteor("todos").find({});
$meteor("todos").insert({
name: "Do something",
done: false
});
I tried to re-write the above as:
var MeteorCtrl = function ($scope, $meteor) {
$scope.todos = $meteor("todos").find({});
$meteor("todos").insert({
name: "Do something",
done: false
})
};
which is still throwing an error 'Error: Unknown provider: $meteorProvider <- $meteor'
The only other example of meter+angularjs at https://github.com/bevanhunt/meteor-angular-leaderboard appears to be dated.
Can someone please post a simple, but fully working, downloadable example of meteor+angularjs using the package at https://github.com/lvbreda/Meteor_angularjs?
I'm obviously biased but our team wrote and maintain this library - angular-meteor and we've also released a tutorial for combining the two - angular-meteor tutorial
While I'm not using lvbreda's Angular package, I have been able to integrate Angular with Meteor + Blade as the HTML templating language, in a relatively simple way. I started off with Daniel Olano's Ng-Meteor package, and ended up with my own implementation of a Meteor/Angular bridge. I'm new to both Meteor and Angular, but it appears to work well and I like that the code is very transparent so that I understand pretty well how it works.
I've written the following CoffeeScript module, named client/ngMeteor.coffee, which defines the bridge between Meteor and Angular:
define("ngMeteor", [], ->
angular.module('ngMeteor.directives', [])
angular.module('ngMeteor.services', [])
angular.module('ngMeteor.blade', []).run(['$templateCache', '$rootScope', '$compile',
($templateCache, $rootScope, $compile) ->
bodyTemplate = Template.body
if !bodyTemplate
throw new Error("A body template must be defined ('body.blade')")
# Render each template and place in Angular's template cache
$templateCache.put "#{key}.blade", render() for own key, render of Template
# Render the body template and have Angular compile it, then inject it into the DOM's body element
Meteor.startup(()->
# Necessary?
Spark.finalize(document.body)
$('html').attr('data-ng-app', '')
$('body').html($compile(bodyTemplate())($rootScope))
$rootScope.$apply()
)
])
angular.module 'ngMeteor', ['ngMeteor.blade', 'ngMeteor.services', 'ngMeteor.directives']
)
For a full working example see this example project of mine. Feedback is appreciated.
I just created a simple example which shows how to create a simple angular-meteor application.
The app displays some items from a mongo collection and can update the collection through the browser-console in realtime. (just default meteor features with angular-js)
It can be found on github: https://github.com/tom-muhm/angular-meteor-example.
You can find some examples in a different fork
https://github.com/alex-okrushko/Meteor_angularjs
I build an app in https://github.com/linepos/linepos but now it's not working because lvbreda changed the code
There is a different approach you can use https://github.com/kievechua/flame-on
Just had the same problem. Solved by adding meteor dependency
angular.module('meteorapp', ["meteor"]) # <------------------- Here
.config ['$routeProvider', '$locationProvider', ($routeProvider, $locationProvider) ->
$locationProvider.html5Mode(true)
$routeProvider.when '/',
controller: 'home'
]
I am also new to Meteor and Angular - and I also had a hard time to make this work. But I think I managed to get the basic Angular functionality running.
What I found out I put onto github: https://github.com/dirkk0/angularjs-meets-meteorjs
I hope this works for you, too.
I've been going at this problem myself and made a package for angural.
example code is at: https://github.com/bramtervoort/meteor-angular-stack/tree/example
example at: http://bramtervoort-todo.meteor.com
Its very simple just install meteor and run: mrt add angular-stack
My answer will be simple: don't mix meteor and angular!
Why should you?
For the data binding capabilities? Meteor does it for you much simpler than angular with helpers and the publish/subscribe mechanism.
To build you own directives? Meteor templates and Blaze do that for you too.
After having used angular for quite a while, I've used meteor recently and find it so much simpler: much less code to achieve the same, cleaner declaration of directives, a whole lot is done for you in the background, especially for pulling subsets of data.
There is no need to use angular with meteor, just use meteor. I haven't yet found a case where I needed angular with it.
The hardest concept to grasp in meteor is the publish subscribe model but once you get it, it is very powerful as you can define what data is pushed to the client with parameters. Then all you need is a template to render it.
Lookup this article for more details
https://www.discovermeteor.com/blog/understanding-meteor-publications-and-subscriptions/
EDIT: Jan 2016
Looking at benchmarks of Angular 2 in Meteor, I now can see a reason maybe to use it. That was definitely not the case with prior versions:
See the article:
http://info.meteor.com/blog/comparing-performance-of-blaze-react-angular-meteor-and-angular-2-with-meteor
Angular 1.x was way way slower than Blaze and React just 6 months ago. Angular 2 seem way better, yet I'm still not a fan of the over-complexity.
For simplicity AND speed, also look up Aurelia.io built by former Angular lead and designed to last and move with the Javascript framework itself.
A similar question was asked here but it did not help me.
I am learning angularjs and I noticed the controller is executed twice.
I have a very simple fiddle example that shows the behavior here
I built the example as I was learning about services and at first I thought it was the injecting of the services into the controller but I commented all the code related to the services and still the controller is executed twice.
My example works but I am afraid I am doing something wrong.
<div ng-app="MyApp">
<div ng-controller="MyCtrl">
{{data1}}
</div>
</div>
var app = angular.module('MyApp', [])
app.service('Service1', function(){
return {
ajxResponse1: 'dataFromService1'
};
});
function MyCtrl($scope, Service1){
alert('Entering MyCtrl');
$scope.data1 = Service1.ajxResponse1;
alert('Exiting MyCtrl');
}
One possible source is this: if you are using Routing and specify the controller in routes - you must not specify it in template that the route uses. We had that problem when this was overlooked.
Your controller was running twice in the fiddle because angular is referenced twice (once via the Frameworks & Extensions drop down and another as an External Resource).
See this updated fiddle where I removed the External Resource and the alerts only show up once.
The code remains unchanged:
function MyCtrl($scope, Service1, Service2, Service3){
alert('Entering MyCtrl');
$scope.data1 = Service1.ajxResponse1;
$scope.data2 = Service2.ajxResponse2;
$scope.data3 = Service3.ajxResponse3;
alert('Exiting MyCtrl');
}
I had a similar problem and it was due to slashes in my routing.
I had something like /post{slug:[a-z0-9-]*/} for my route and when visiting the page at domain.com/post it would redirect to the version with a slash on the end.
Took me ages to work it out!
Edit:
Actually, just took a more detailed look at your code and noticed there is no routing in there, so this is probably not the cause in your case.
Might be useful for people like me who were looking for a different solution though.
For all the people using rails and angularjs:
The rails framework that maps URLS to views and loads them clashes with the angularjs $route even when you have a single-view application.
To prevent the double-loading of your controller:
go to application.js and remove "//= require turbolinks
You're welcome.
I'm trying to "customize" the mongolab example to fit my own REST API. Now I'm running into this error and I am not sure what I am doing wrong:
Error: Unknown provider: ProductProvider <- Product
at Error (unknown source)
at http://localhost:3000/js/vendor/angular.min.js:28:395
at Object.c [as get] (http://localhost:3000/js/vendor/angular.min.js:26:180)
at http://localhost:3000/js/vendor/angular.min.js:28:476
at c (http://localhost:3000/js/vendor/angular.min.js:26:180)
at d (http://localhost:3000/js/vendor/angular.min.js:26:314)
This is my controller:
function ProductListCtrl($scope, Product) {
$scope.products = Product.query();
}
and this is the module:
angular.module('productServices', ['ngResource']).
factory('Product', ['$resource', function($resource){
var Product = $resource('/api/products/:id', { }, {
update: { method: 'PUT' }
});
return Product;
}]);
Your code looks good, in fact it works (apart from the calls themselves) when copied & pasted into a sample jsFiddle: http://jsfiddle.net/VGaWD/
Hard to say what is going on without seeing a more complete example but I hope that the above jsFiddle will be helpful. What I'm suspecting is that you are not initializing your app with the 'productServices' module. It would give the same error, we can see this in another jsFiddle: http://jsfiddle.net/a69nX/1/
If you are planning to work with AngularJS and MongoLab I would suggest using an existing adapter for the $resource and MongoLab: https://github.com/pkozlowski-opensource/angularjs-mongolab
It eases much of the pain working with MongoLab, you can see it in action here: http://jsfiddle.net/pkozlowski_opensource/DP4Rh/
Disclaimer! I'm maintaining this adapter (written based on AngularJS examples) so I'm obviously biased here.
I got that error because I was passing an incorrect parameter to the factory definition. I had:
myModule.factory('myService', function($scope, $http)...
It worked when I removed the $scope and changed the factory definition to:
myModule.factory('myService', function( $http)...
In case you need to inject $scope, use:
myModule.factory('myService', function($rootScope, $http)...
I just had a similar problem.
The error said the same the in the question, tried to solve it with the answer of pkozlowski.opensource and Ben G, which both are correct and good answers.
My problem was indeed different with the same error:
in my HTML-Code I had the initialisation like this...
<html ng-app>
A bit further down I tried to do something like this:
<div id="cartView" ng-app="myApp" ng-controller="CartCtrl">
I got rid of the first one... then it worked... obviously you can't initialise ng-app twice or more times. fair enough.
I totaly forgot about the first "ng-app" and got totaly frustrated. Maybe this is gonna help someone oneday...
Make sure your main app.js includes the services on which it depends. For example:
/* App Module */
angular.module('myApp', ['productServices']).
.....
pkozlowski's answer is correct, but just in case this happens to someone else, I had the same error after creating the same module twice by mistake; the second definition was overriding the provider of the first:
I created the module by doing
angular.module('MyService'...
).factory(...);
then a bit further down in the same file:
angular.module('MyService'...
).value('version','0.1');
The correct way of doing this is:
angular.module('MyService'...
).factory(...).value('version','0.1');
In my case, I've defined a new provider, say, xyz
angular.module('test')
.provider('xyz', function () {
....
});
When you were to config the above provider, you've to inject it with Provider string appended --> xyz becomes xyzProvider.
Ex:
angular.module('App', ['test'])
.config(function (xyzProvider) {
// do something with xyzProvider....
});
If you inject the above provider without the 'Provider' string, you'll get the similar error in OP.
At the end of the JS file to close the factory function I had
});
instead of
}());
This took me way too long to track down. Make sure you minisafe your controller within your directive.
.directive('my_directive', ['injected_item', function (injected_item){
return {
controller: ['DO_IT_HERE_TOO', function(DO_IT_HERE_TOO){
}]
}
}
Hope that helps
To add my own experience in here, I was trying to inject a service into one of my module config functions. This paragraph from the docs which I eventually found explains why that doesn't work:
During application bootstrap, before Angular goes off creating all services, it configures and instantiates all providers. We call this the configuration phase of the application life-cycle. During this phase, services aren't accessible because they haven't been created yet.
Meaning you can inject providers into module.config(...) functions, but you can't inject services, for that you need to wait until module.run(...), or expose a provider you can inject to module.config
For me, this error was caused by running the minified version of my angular app. Angular docs suggest a way to work around this. Here is the relevant quote describing the issue, and you can find the suggested solution in the docs themselves here:
A Note on Minification
Since Angular infers the controller's dependencies from the names of arguments to the controller's constructor function, if you were to minify the JavaScript code for PhoneListCtrl controller, all of its function arguments would be minified as well, and the dependency injector would not be able to identify services correctly.
Since this is the top result for "angularjs unknown provider" on Google right now, here's another gotcha. When doing unit testing with Jasmine, make sure you have this statement in your beforeEach() function:
module('moduleName');
Otherwise you'll get this same error in your tests.
Yet another case where this error will occur, if you're service is defined in a separate javascript file, make sure you reference it! Yes, I know, rookie mistake.
I was forgetting to inject the file that held my services altogether. Remember to do this when initializing your app module:
angular.module('myApp', ['myApp.services', ... ]);
In my case, I used an anonymous function as a wrapper for the angular module, like this:
(function () {
var app = angular.module('myModule', []);
...
})();
After closing the parenthesis, I forgot to call the anonymous function by opening and closing the parentheses again as above.
For me the problem was lazy loading; I loaded my controller and service late, so they were not available at page load (and Angular initialization). I did this with an ui-if tag, but that's irrelevant.
The solution was to load the service with the page load already.
Here's another possible scenario where you can see this error:
If you use Sublime Text 2 and the angular plugin, it will generate stubs like this
angular.module('utils', [])
.factory('utilFactory', [''
function() {
return {
}
}
]);
notice the empty ' ' as the first element of the array after the 'utilFactory' string. If you don't have any dependencies, remove that so it's like this:
angular.module('utils', [])
.factory('utilFactory', [
function() {
return {
}
}
]);
Since this question is top google result, I will add another possible thing to the list.
If the module that you're using has a failure on the dependency injection wrapper, it will provide this same result. For example copy & paste modules from the internet may rely on underscore.js and attempt to inject with '_' in the di wrapper. If underscore doesn't exist in your project dependency providers, when your controller attempts to reference your module's factory, it will get 'unknown provider' for your factory in the browser's console log.
The problem for me was that there were some new javascript files I created that referenced the service yet Chrome saw only the older version. A CTRL + F5 fixed it for me.
I got an "unknown provider" error related to angular-mocks (ngMockE2E) when compiling my project with Grunt. The problem was that angular-mocks cannot be minified so I had to remove it from the list of minified files.
After handling with this error too, I can support this list of answers with my own case.
It's at the same time simple and dumb (maybe not dumb for beginners like me, but yes for experts), the script reference to angular.min.js must be the first one in your list of scripts in the html page.
This works:
<script src="Scripts/angular.min.js"></script>
<script src="MyScripts/MyCartController.js"></script>
<script src="MyScripts/MyShoppingModule.js"></script>
This not:
<script src="MyScripts/MyCartController.js"></script>
<script src="MyScripts/MyShoppingModule.js"></script>
<script src="Scripts/angular.min.js"></script>
Notice about the angular.min.js.
Hope it helps anyone !! :)
My problem was with Yeoman, using (capitalized):
yo angular:factory Test
Made files (uncapitalized):
app/scripts/services/test.js
but the index.html file included (capitalized):
<script src="scripts/services/Test.js"></script>
Hope this helps someone.
Yet another possibility.
I had unknown Provider <- <- nameOfMyService. The error was caused by the following syntax:
module.factory(['', function() { ... }]);
Angular was looking for the '' dependency.
My scenario may be a little obscure but it can cause the same error and someone may experience it, so:
When using the $controller service to instantiate a new controller (which was expecting '$scope' as it's first injected argument) I was passing the new controller's local scope into the $controller() function's second parameter. This lead to Angular trying to invoke a $scope service which doesn't exist (though, for a while, I actually thought that I'd some how deleted the '$scope' service from Angular's cache). The solution is to wrap the local scope in a locals object:
// Bad:
$controller('myController', newScope);
// Good:
$controller('myController, {$scope: newScope});
None of the answers above worked for me, maybe I was doing completely wrong, but as a beginner that's what we do.
I was initializing the controller in a div in order to have a list:
<div ng-controller="CategoryController" ng-init="initialize()">
And then using $routeProvider to map a URL to the same controller. As soon as I removed the ng-init the controller worked with the route.
I had same problem. I fixed that using $('body').attr("ng-app", 'MyApp') instead of <body ng-app="MyApp"> to boostrap.
Because I did
angular.element(document).ready(function () {
angular.bootstrap(document, [App.Config.Settings.AppName]);
})
for architecture requirements.
In my Ruby on Rails app, I had done the following:
rake assets:precompile
This was done in the 'development' environment, which had minified Angular.js and included it in the /public/assets/application.js file.
Removing the /public/assets/* files solved the problem for me.
I faced similar issue today and issues was really very small
app.directive('removeFriend', function($scope) {
return {
restrict: 'E',
templateUrl: 'removeFriend.html',
controller: function($scope) {
$scope.removing = false;
$scope.startRemove = function() {
$scope.removing = true;
}
$scope.cancelRemove = function() {
$scope.removing = false;
}
$scope.removeFriend = function(friend) {
var idx = $scope.user.friends.indexOf(friend)
if (idx > -1) {
$scope.user.friends.splice(idx, 1);
}
}
}
}
});
If you observe the above block, in the first line you will observe I injected $scope by mistake which is incorrect. I removed that unwanted dependency to solve the issue.
app.directive('removeFriend', function() {
return {
restrict: 'E',
templateUrl: 'removeFriend.html',
controller: function($scope) {
$scope.removing = false;
$scope.startRemove = function() {
$scope.removing = true;
}
$scope.cancelRemove = function() {
$scope.removing = false;
}
$scope.removeFriend = function(friend) {
var idx = $scope.user.friends.indexOf(friend)
if (idx > -1) {
$scope.user.friends.splice(idx, 1);
}
}
}
}
});
I had this error after I created a new factory and used it within a component but I did not check the specs of that components
so if the failure in your (specs) test files
you need to add beforeEach(module('YouNewServiceModule'));
Another 'gotcha': I was getting this error injecting $timeout, and it took a few minutes to realize I had whitespace in the array values. This will not work:
angular.module('myapp',[].
controller('myCtrl', ['$scope', '$timeout ',
function ($scope, $timeout){
//controller logic
}
]);
Posting just in case some else has a silly error like this.
My case was dodgy typing
myApp.factory('Notify',funtion(){
function has a 'c' !