I want 'MyController2' to inherit 'MyController1', however, both controllers are lazyloaded using ocLazyLoad. According to Jussi Kosunen's answer to this question (https://stackoverflow.com/a/15292441/2197555), I have made a function registerDynamic() to register the controllers, but it still reports the following error at the line with '$controller' in controller1.js:
Error: [$injector:unpr] Unknown provider: $elementProvider <- $element <- DataTableController
My codes are like this.
First file controller1.js:
angular.module( 'myApp',[])
.controller( 'MyController1', [ function($scope){
// ...
}]);
Second file controller2.js:
angular.module( 'myApp')
.controller( 'MyController2', [ '$controller', '$scope',function($controller, $scope){
$controller('MyController1', {$scope: $scope }); // here triggers error '[$injector:unpr] Unknown provider'
// ...
}]);
In the third File lazy-load.js, I lazyload the above two .js files:
var app = angular.module('myApp'),
queueLen = app._invokeQueue.length;
app.directive( 'LazyLoad', [ function( ){
return {
restrict: 'EA',
scope: {
src: '#',
},
link: function( scope, element, attr ){
var registerDynamic = function() {
// Register the controls/directives/services we just loaded
var queue = syncreonApp._invokeQueue;
for(var i=queueLen;i<queue.length;i++) {
var call = queue[i];
// call is in the form [providerName, providerFunc, providerArguments]
var provider = syncreonApp.providers[call[0]];
if(provider) {
// e.g. $controllerProvider.register("Ctrl", function() { ... })
$log.debug("Registering " + call[1] + " " + call[2][0] + " ...");
provider[call[1]].apply(provider, call[2]);
}
}
queueLen = i;
},
loadMultipleJs = function ( js_files ){
var deferred = $q.defer();
var js_file1 = js_files.shift(),
js_file2 = js_files.shift();
$ocLazyLoad.load( js_file1 )
.then ( function(){
registerDynamic();
$ocLazyLoad.load( js_file2 )
.then ( function(){
registerDynamic();
deferred.resolve();
}, function(){
deferred.reject();
});
}, function(){
deferred.reject();
});
};
jsonOfJsFilesToLoad = JSON.parse(scope.src);
loadMultipleJs(jsonOfJsFilesToLoad );
}
};
}]);
UPDATE
The official Angular documentation for 'Unknown Provider' error says:
Attempting to inject one controller into another will also throw an Unknown provider error:
Maybe we just cannot injector controller into anther even using $controller service?
You are taking the error message out of context.
Attempting to inject one controller into another will also throw an Unknown provider error:
angular.module('myModule', [])
.controller('MyFirstController', function() { /* ... */ })
.controller('MySecondController', ['MyFirstController', function(MyFirstController) {
// This controller throws an unknown provider error because
// MyFirstController cannot be injected.
}]);
That is not the way you are instantiating controllers.
It specifically says:
Use the $controller service if you want to instantiate controllers yourself.
Which is the way you are instantiating your controllers.
Look for your problem elsewhere.
Your error message:
Unknown provider: $elementProvider <- $element <- DataTableController
The way I read this is that in your DataTableController, you are trying to inject $element. $element is not a service is a local. To inject $element as a local with the $controller service:
$controller('DataTableController', {$scope: $scope, $element: value });
Related
I read an answer about "dynamic factory" from How to create Dynamic factory in Angular js?
It works great but some additional conditions required for my project make me tired.
conditions are simple.
There is a button that trigger dynamic directive element. From now we call the original background's scope 'ParentScope' and directive's 'ChildScope'.
At the same time, 'ParentScope' dynamically make factory named "ex2-service".
This directive's controller needs to inject "ex2-service".
above simple example is http://jsfiddle.net/chaht01/QM52v/29/
jscode below
var app = angular.module("myApp", [])
.service("echo", function() {
return {
echo: function(msg) {
console.log(msg);
return msg;
}
};
}), makeService = function(module, identifier) {
module.factory(identifier+'-service', ['echo', function(echo) {
return {
run: function(msg) {
return echo.echo(identifier + ": " + msg);
}
};
}]);
};
makeService(app, 'ex1');
app.controller("myController", ['ex1-service',
'$injector',
'$scope',
function(service, $injector, $scope) {
$scope.service1 = service.run('injected.');
$scope.test = function(){
$scope.isReady = true;
makeService(app, 'ex2');
}
}]).controller("child",['ex2-service','$scope',function(service,$scope){
$scope.service2 = service.run('dynamically injected')
}])
when I click button, get error like
Error: [$injector:unpr] Unknown provide: ex2-serviceProvider <- ex2-service
how can I solve this problem??
I have created and injected the service(myService) into my app (app) , but it is not working. The error implies that I have not defined the service anywhere:
Error: [$injector:unpr] Unknown provider: myServiceProvider <- myService <- myController
myService calls another service - ajaxService to do the actual http call.
The only reason I would think that myService throws the above error when trying to call it in myController is because I have another module defined in the app definition (common.components). This module has its own separate services which I am using elsewhere in my app. I am wondering if the app is searching for a definition of myService within that the common.components module instead of inside itself.
Here is my code:
- app.js
var app = angular.module('app ', ['ngRoute','common.components']);
- myService.js
var serviceId = 'myService';
angular.module('app').service(serviceId,['$q','ajaxService','$log',myService]);
function myService($q, ajaxService, $log){
var states = [];
this.getStates = function() {
var defered = $q.defer();
ajaxService.getStates().then(function(result){
states = result.data;
defered.resolve(states);
},
function(error){
deferred.reject();
});
return defered.promise;
};
}
- ajaxService.js
var serviceId = 'ajaxService';
angular.module('app',[]).service(serviceId,['$http','$log',ajaxService]);
function ajaxService($http,$log){
this.getStates = function() {
return $http.get('./json/DATA.json');
};
}
myController.js
(function(){
'use strict';
angular.module('app').controller('myController',['$scope','$log','myService',myController]);
function myController($scope,$log,myService){
$scope.states = [];
myService.getStates().then(function(states){
$scope.states = states;
});
}
})();
I have been trying to find out what is wrong for hours, but I am lost. Can someone help me with this?
I have updated my answer as you have now provided more info.
Your issue is in your ajaxService.js
Change this line
angular.module('app',[]).service(serviceId,['$http','$log',ajaxService]);
to this
angular.module('app').service(serviceId,['$http','$log',ajaxService]);
Your are recreating the app module by adding the [].
My code as follows :
var module = ons.bootstrap('my-app', ['onsen','ngSanitize','ngCookies','ngStorage']);
module.factory('methodService', [ '$scope', '$timeout', '$http',
'$localStorage', 'alertService',
function($scope, $timeout, $http, $localStorage, alertService){
}]);
module.factory('alertService', function () {
var data = {
title: 'Alert',
message: ''
}
return {
getTitle: function () {
return data.title;
},
setTitle: function (title) {
data.title = title;
},
getMessage: function () {
return data.message;
},
setMessage: function (message) {
data.message = message;
},
alert : function(){
ons.notification.alert({
message: data.message,
title: data.title
});
}
};
});
And there is a error Error: [$injector:unpr] Unknown provider: $scopeProvider <- $scope <- methodService
Anybody knows the reason and how to solve it?
You're misunderstanding about 2 things :
As said in comments the $scope is a special variable that can only be injected in controllers
The scope object injected in the controller is different for every controller. It's not the same instance of the object. Angular is build like this : you have a $rootScope. Every other $scope inherits from that $rootScope or from another $scope. It's a tree hierarchy. Thanks to the inheritance, you can retrieve data stored in a parent $scope.
My advise : don't store $scope, don't spam the $rootScope. Just store what you need in the $scope of your controller and call your factory layer properly like this :
$scope.myObjectToCreate = {};//object that wll be field in a form
$scope.createObject = function(){
myService.create($scope.myObjectToCreate);
}
//or
$scope.createObject = function(object){
myService.create(object);
}
// but NEVER DO THIS
$scope.createObject = myService.create;
The last point is about the scope of the function that will change, every use of this in the function myService.create will make it crash. Because this wil refer to $scope instead of myService
I am trying to extend the $log service so that it also sends a message to a server. I am getting an error from Angular "Circular dependency found" as $http uses $log.
app.js:
angular.module("app").config(function($provide) {
$provide.decorator("$log", function($delegate, NodeLogger) {
var logFn = $delegate.log;
$delegate.log = function(message) {
NodeLogger.log(message);
logFn.apply(null, arguments);
};
});
});
NodeLogger.js:
angular.module("app").factory("NodeLogger", function($http) {
function log(type, message) {
var logMessage = type + ":" + message;
$http.post("http://localhost:3000/log", "message=" + logMessage);
}
return {
log: log
}
});
I have tried using $injector in app.js to load $http and just make the POST request, but it gives the same error. Is there a way to get around this? Can I avoid using $http / $resource?
Thanks!
This is a common issue of circular dependency when $http already injects $log and by decorating it with injecting your factory NodeLogger which inturn injects $http you are creating circular dependency. Instead of injecting your factory directly get the factory from injector, another way is to inject the $injector in your factory and get the $http instance from injector instead of injecting $http directly. This way you avoid circular dependency during factory creation. One important note is to return $delegate without which $log service will not hold any instance.
$provide.decorator("$log", function($delegate, $injector) {
var logFn = $delegate.log;
$delegate.log = function(message) {
//Get NodeLogger factory instance from injector
var NodeLogger = $injector.get('NodeLogger');
NodeLogger.log(message);
logFn.apply(null, arguments);
};
//Return the delegate
return $delegate;
});
angular.module("app", []).factory("NodeLogger", function($http) {
function log(type, message) {
var logMessage = type + ":" + message;
$http.post("http://localhost:3000/log", "message=" + logMessage);
}
return {
log: log
}
}).config(function($provide) {
$provide.decorator("$log", function($delegate, $injector) {
var logFn = $delegate.log;
$delegate.log = function(message) {
var NodeLogger = $injector.get('NodeLogger');
NodeLogger.log(message);
logFn.apply(null, arguments);
};
return $delegate;
});
}).run(function($log) {
$log.log("Hey");
});;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<div ng-app="app"></div>
I've got this in app.js:
angular.module('App',[]).config(['TranslationProvider', function (TranslationProvider) {
//codes...
}]);
And this service in another file:
angular.module('App')
.provider('Translation', function() {
var translations = {foo:"bar"}
this.$get = function(){
return translations;
};
});
No 404 error with the service js file, but when angular injector try to instantiate it gives me this error:
Uncaught Error: [$injector:modulerr] Failed to instantiate module App due to:
Error: [$injector:unpr] Unknown provider: TranslationProvider
I've followed the angjs documentation https://docs.angularjs.org/guide/providers
It seems to be a bug in Angular 1.2.x. The order of the calls matter. When you call provide before config it works. It also works with Angular 1.3.x regardless of the order.
You are almost there.
First the config:
angular.module('App')
.config(["TranslationProvider", function(theProvider) {
console.log("in config" + theProvider)
theProvider.setName("some name");
}]);
The error you were having was due to you using the constructor function as an argument.
Now your provider:
angular.module('App')
.provider('Translation', function TranslationProvider() {
var translations = {foo:"bar", name:""};
var dynamicName;
this.setName = function(configName) {
dynamicName = configName;
};
this.$get = function(){
translations.name = dynamicName;
return translations;
};
});
Also note that an anonymous function (i.e. .provider('Translation', function () {) could also have been used and the code would have worked just as well.
Using it all in a controller:
angular.module('App')
.controller('MyController', [
'$scope',
'Translation',
function ($scope,
translationProvider) {
$scope.modal = {};
$scope.projects = [];
console.log(translationProvider)
$scope.foo = translationProvider;
}]);