I was implementing angular translate in my project and everything works fine, but when I've moved my $translateProviderfrom my config block to my controller.js, I'm getting this error:
Unknown provider: $translateProviderProvider <- $translateProvider <-
myController
But every module seems to be correctly referenced, am I missing something here? or maybe this translations can't work inside of a controller?
controller.js
angular.module('myapp.controller', ['pascalprecht.translate'])
.controller('myController',
['$translateProvider',
function ($translateProvider) {
function init() {
$translateProvider.useUrlLoader('myweb.com/api/lang', {
queryParameter : 'en_US'
});
$translateProvider.preferredLanguage('en_US');
}
init();
}]);
UPDATE
Now I know that $translateProvider are not available to use it in controller class.
What I'm trying to accomplish:
I don't want to load all the traductions files from the rest, because there are many components that the user never see, so if I go to the page that contains ng-controller="myController", the init() function should call to the rest and get the traductions only for the current component. I've found this on the documentation:
angular.module('contact')
.controller('ContactCtrl', function ($scope, $translatePartialLoader) {
$translatePartialLoader.addPart('contact');
});
But how can I:
Specify the URL for my REST?
Specify the parameter 'contact' in the URL to my REST know that it should retrieve me the traductions only for the contact component.
When injecting a provider in a controller, you don't need the Provider suffix.
just inject it as
.controller('myController', ['$translate', function ($translate) { ... }])
Related
In my angular application I want to go to another page on a click of a button. For that I use GoNext function. Below is my code that gives me state is not defined error. Can anyone tell me what is going on?
(function () {
angular.module("MyApp").controller("MainCtrl", ["$scope", "$state", "$http", MainCtrlFunction]);
function MainCtrlFunction($scope, $state, $http) {
....
$scope.GoNext = function () {
state.go("screen2");
}
}
})();
I do have a corresponding entry in my config file.
You've miss typed the service $state's name. It's just a confusion because you have two things named state on your code: the argument $state which is a service and the state of your aplication router; Anyways, it should look like:
$state.go("screen2");
Instead of:
state.go("screen2");
Need to use $state and make sure it's injected into your controller. Seems you used state w no dollar symbol.
I'm trying to create a custom filter, but when I try to inject it into my controller, I get an 'Unknown provider' error. I have checked and double checked all the references, but I can't see what's wrong.
I know that the file is referenced in my index.html correctly, it is loaded and can be found by the inspector. This is the code I have:
In my app.js:
angular.module('equiclass', ['equiclass.controllers',
'equiclass.services',
'ngRoute'])
.config(function ($routeProvider) {
$routeProvider
.when('/courses', {
templateUrl: 'views/courses.html',
controller: 'CourseCtrl'
// And some other stuff with routes
});
angular.module('equiclass.controllers', ['equiclass.services', 'equiclass.filters']);
angular.module('equiclass.services', []);
angular.module('equiclass.filters', []);
My filter:
angular.module('equiclass.filters')
.filter('testFilter', function() {
return function(input) {
return undefined;
};
});
And the controller:
angular.module('equiclass.controllers')
.controller('CourseCtrl', function ($scope, testFilter) {
});
Of course this is quite simplified, but it just doesn't work, and I can't see why. I have made several services and they all work and play along nicely.
If you want to use filter inside a controller you have to inject $filter attribute to your controller and can access it like
$filter('filtername');
You can use like
function myCtrl($scope, $filter)
{
$filter('filtername')(arg1,arg2);
}
You don't need to inject the filter itself.
This code...
angular.module('equiclass.controllers')
.controller('CourseCtrl', function ($scope, testFilter) {
});
Should be
angular.module('equiclass.controllers')
.controller('CourseCtrl', function ($scope) {
});
And inside CourseCtrl you should use your filter as you normally do.
Injecting the module 'equiclass.filters' into your module 'equiclass.controllers' is enough.
I had a similar issue and made a post about it on my blog.
--Edit
As n00dl3 mentions below the tricky part is how the auto-naming convention works in Angular. If you name your filter specialNumberFilter then when you inject it you need to refer to it as specialNumberFilterFilter. This allows you to use the filter as a function, which is what it is.
// In a controller
vm.data = specialNumberFilterFilter(vm.data, 'a');
But I believe you can also use the filter without injecting it into a controller if it is used in a string expression that is being evaluated by, say, a watch because this would be the same as the scenario when you are using it in a template.
// Inside a watch - no controller injection required
`$scope.$watch('vm.data | specialNumberFilter', function(new, old) { ... })`
According to Angular's documentation :
if you want to use your filter in a template
then you just need to inject it in your module and then use it like this {{ expression | filter }} or {{ expression | filter:argument1:argument2:... }} .
doc
if you want to use your filter in a controller, directive, and stuffs :
inject a dependency with the name <filterName>Filter, like this :
controller('MyController', ['filterFilter', function(filterFilter) {}]);
doc
so for this particular case :
angular.module('equiclass.controllers')
.controller('CourseCtrl', function ($scope, testFilterFilter) {
});
you didn't mention if it's in production or on a local server, but just in case you are minifying your files, try this:
angular.module('equiclass.controllers')
.controller('CourseCtrl', ['$scope', 'testFilter', function ($scope, testFilter) {
}]);
I'm confused about how to create services and inject (use) them in my controllers. It seems it is very simple but I can't get my code to work. I'm stuck with this error:
Error: [$injector:unpr] Unknown provider: Flickr
I define the service:
angular.module('myApp.services', [])
.provider('Flickr', function(){
// service code
})
Include it in my app module:
var app = angular.module('myApp', [
'ngResource',
'ngRoute',
'myApp.services'
]);
and then reference it in a controller:
app.controller('FlickrCtrl', ['$scope', '$routeParams', 'Flickr', function($scope, $routeParams, Flickr){
// controller stuff
});
and reference the files at the bottom of index.html
<script src='js/app.js'></script>
<script src='js/config.js'></script>
<script src='js/services/Flickr.js'></script>
<script src='js/controllers/flickr.js'></script>
Why can't angular find the service I defined when I ask it to inject it into the controller?
When using .provider, you are creating a provider that should return a configurable singleton. In many cases, this singleton is a singleton factory, spitting back an object that has services you can use.
First, you would need to refer to it as FlickrProvider instead of Flickr when you call it to set a config.
Without seeing more of your code, I can't tell if you're returning a new Flickr from your provider, which is what you would need to do in order to use a service instance in the way I think you're trying to do.
check out: http://docs.angularjs.org/guide/providers
Basically though, in order to inject and use Flickr like you are trying to do, you would need to do something like this:
.provider('Flickr',function FlickrProvider(){
this.$get = function(){
return new Flickr()
}
})
function Flickr(){
this.doSomething: function(){
//do something or return something
}
}
If you only want to define a service, and not make it a configurable provider, then use .factory instead, which will only need Flickr to be injected in order to be used.
I read a lot about lazzy loading, but I am facing a problem when using $routeProvider.
My goal is to load a javascript file which contains a controller and add a route to this controller which has been loaded previously.
Content of my javascript file to load
angular.module('demoApp.modules').controller('MouseTestCtrlA', ['$scope', function ($scope) {
console.log("MouseTestCtrlA");
$scope.name = "MouseTestCtrlA";
}]);
This file is not included when angular bootstap is called. It means, I have to load the file and create a route to this controller.
First, I started writing a resolve function which has to load the Javascript file. But declaring my controller parameter in route declaration gave me an error :
'MouseTestCtrlA' is not a function, got undefined
Here is the call I am trying to set :
demoApp.routeProvider.when(module.action, {templateUrl: module.template, controller: module.controller, resolve : {deps: function() /*load JS file*/} });
From what I read, the controller parameter should be a registered controller
controller – {(string|function()=} – Controller fn that should be associated with newly created scope or the name of a registered controller if passed as a string.
So I write a factory which should be able to load my file and then (promise style!) I whould try to declare a new route.
It gave me something like below where dependencies is an array of javascript files' paths to load :
Usage
ScriptLoader.load(module.dependencies).then(function () {
demoApp.routeProvider.when(module.action, {templateUrl: 'my-template', controller: module.controller});
});
Script loader
angular.module('demoApp.services').factory('ScriptLoader', ['$q', '$rootScope', function ($q, $rootScope) {
return {
load: function (dependencies)
{
var deferred = $q.defer();
require(dependencies, function () {
$rootScope.$apply(function () {
deferred.resolve();
});
});
return deferred.promise;
}
}
}]);
Problem
I still have this javascript error "'MouseTestCtrlA' is not a function, got undefined" which means Angular could not resolved 'MouseTestCtrlA' as a registered controller.
Can anyone help me on this point please ?
Re-reading this article http://ify.io/lazy-loading-in-angularjs/ suggested to keep a $contentProvider instance inside Angular App.
I came up with this code in my app.js
demoApp.config(function ($controllerProvider) {
demoApp.controller = $controllerProvider.register;
});
It enables me to write my controller as expected in a external javascript file :
angular.module("demoApp").controller('MouseTestCtrlA', fn);
Hope this can help !
EDIT: I have managed to get my unit tests running - I moved the code containing the services to a different file and a different module, made this new module a requirement for fooBar module, and then before each "it" block is called, introduced the code beforeEach(module(<new_service_module_name)). However, my application still won't run. No errors in console either. This is the only issue that remains - that when I use global scope for controllers definition, the application works, but when I use angular.module.controller - it does not.
I have a file app.js that contains the following:
'use strict';
var app = angular.module('fooBar', []);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'partials/form-view.html',
controller: FormViewCtrl
}).
when('/resultDisplay', {
templateUrl: 'partials/table-view.html',
controller: TableViewCtrl
}).
otherwise({redirectTo: '/'});
}]);
app.service('searchResults', function() {
var results = {};
return {
getResults: function() {
return results;
},
setResults: function(resultData) {
results = resultData;
}
};
});
I have another file controllers.js that contains the following:
'use strict';
var app = angular.module('fooBar', []);
app.controller('FormViewCtrl', ['$scope', '$location', '$http', 'searchResults',
function ($scope, $location, $http, searchResults) {
//Controller code
}]);
searchResults is a service that I created that simply has getter and setter methods. The controller above uses the setter method, hence the service is injected into it.
As a result, my application just does not run! If I change the controller code to be global like this:
function ($scope, $location, $http, searchResults) {
//Controller code
}
then the application works!
Also, if I use the global scope, then the following unit test case works:
'use strict';
/*jasmine specs for controllers go here*/
describe('Foo Bar', function() {
describe('FormViewCtrl', function() {
var scope, ctrl;
beforeEach(module('fooBar'));
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
ctrl = $controller('FormViewCtrl', {$scope: scope});
}));
}
//"it" blocks
}
If I revert to the module scope, I get the error -
Error: Unknown provider: searchResultsProvider <- searchResults
Thus, by using global scope my application and unit tests run but by using app.controller, they seem to break.
Another point that I have noted is that if I include the controller code in app.js instead of controllers.js, then the application and unit tests start working again. But I cannot include them in the same file - how do I get this to run in the angular scope without breaking the application and unit tests?
You don't need to go that route. You can use the modular approach, but the issue is with your second parameter.
In your app.js you have this:
var app = angular.module('fooBar', []);
Then in your controller, you have this:
var app = angular.module('fooBar', []);
What you're doing there is defining the module twice. If you're simply trying to attach to the app module, you cannot pass in the second parameter (the empty array: []), as this creates a brand new module, overwriting the first.
Here is how I do it (based on this article for architecting large AngularJS apps.
app.js:
angular.module('fooBar',['fooBar.controllers', 'fooBar.services']);
angular.module('fooBar.controllers',[]);
angular.module('fooBar.services', []);
...etc
controllers.js
angular.module('foobar.controllers') // notice the lack of second parameter
.controller('FormViewCtrl', function($scope) {
//controller stuffs
});
Or, for very large projects, the recommendation is NOT to group your top-level modules by type (directives, filters, services, controllers), but instead by features (including all of your partials... the reason for this is total modularity - you can create a new module, with the same name, new partials & code, drop it in to your project as a replacement, and it will simiply work), e.g.
app.js
angular.module('fooBar',['fooBar.formView', 'fooBar.otherView']);
angular.module('fooBar.formView',[]);
angular.module('fooBar.otherView', []);
...etc
and then in a formView folder hanging off web root, you THEN separate out your files based on type, such as:
formView.directives
formView.controllers
formView.services
formView.filters
And then, in each of those files, you open with:
angular.module('formView')
.controller('formViewCtrl', function($scope) {
angular.module('formView')
.factory('Service', function() {
etc etc
HTH
Ok - I finally figured it out. Basically, if you wish to use the module scope and not the global scope, then we need to do the following (if you have a setup like app.js and controllers.js):
In app.js, define the module scope:
var myApp = angular.module(<module_name>, [<dependencies>]);
In controllers.js, do not define myApp again - instead, use it directly like:
myApp.controller(..);
That did the trick - my application and unit tests are now working correctly!
It is best practice to have only one global variable, your app and attach all the needed module functionality to that so your app is initiated with
var app = angular.module('app',[ /* Dependencies */ ]);
in your controller.js you have initiated it again into a new variable, losing all the services and config you had attached to it before, only initiate your app variable once, doing it again is making you lose the service you attached to it
and then to add a service (Factory version)
app.factory('NewLogic',[ /* Dependencies */ , function( /* Dependencies */ ) {
return {
function1: function(){
/* function1 code */
}
}
}]);
for a controller
app.controller('NewController',[ '$scope' /* Dependencies */ , function( $scope /* Dependencies */ ) {
$scope.function1 = function(){
/* function1 code */
};
}
}]);
and for directives and config is similar too where you create your one app module and attach all the needed controllers, directives and services to it but all contained within the parent app module variable.
I have read time and time again that for javascript it is best practice to only ever have one global variable so angularjs architecture really fills that requirement nicely,
Oh and the array wrapper for dependencies is not actually needed but will create a mess of global variables and break app completely if you want to minify your JS so good idea to always stick to the best practice and not do work arounds to get thing to work
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 inject it with 'Provider' string appended.
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.