How to use module function inside another factory in angularjs - angularjs

I have configurations.js file which having
var configurationModule = angular.module('configuration', ['restangular', 'notification']);
configurationModule.factory('clientConfigSvc', function (notificationMgr, $interpolate, $injector) {
function getConfig(configKey) {
return getNestedPropertiesByString(activeEnvironment, configKey);
}
}
and having another javascript file with below code
angular.module('ds.coupons').factory('CouponsREST', ['Restangular', 'SiteConfigSvc', 'settings',function (Restangular, siteConfig, settings, configurationModule) {
configSvc.getConfig('services.baseUrl'); /// need to call this function
}
Actually i want function configSvc.getConfig inside second angular factory

Yes After tired of trying lots of solution, today morning working on moving train got idea to fix, dont know if its correct way but its working. but still looking for correct fix if mine was not correct as per angularjs practise.
Here is my solution.
1. I added configuration module in app.js alogn with other
window.app = angular.module('ds.app', [
'restangular',
'ui.select',
'ui.router',
'ds.shared',
'ds.utils',
'ds.i18n',
'configuration']);
I added clientConfigSVC in my factory where i want to use configuration function
angular.module('ds.coupons')
.factory('CouponsREST', ['Restangular', 'SiteConfigSvc','settings', 'clientConfigSvc',
function(Restangular, siteConfig, settings, clientConfig) { }
and then inside CouponsREST factory with function clientConfig.getConfig() i am getting value

Related

AngularJS call function from a directive in a different file

At first I searched a lot about this question, used some suggestions but couldn't get results.
I had one js file, main.js, where there was only one controller and everything worked fine:
var app = angular.module('monitoringApp', ['ui.bootstrap', 'ngCookies', 'angularCharts','angularUtils.directives.dirPagination','ngLoadScript','ngRoute','dragtable']);
app.controller('mainController', ['$scope', '$http', '$cookies', '$cookieStore' , '$location', function($scope, $http, $cookies, $cookieStore,$location) {
//some function which i need to call;
}
I've added a library for drag and drop table columns dragtable.js and inside dragEnd() function I want to call some function inside main.js
var project = angular.module("dragtable", []);
project.directive('draggable', function($window, $document) {
function dragEnd($event) { need to call function inside main.js }
}
Please note that I already tried to use shared service but still getting error undefined on the function which is called.
It doesn't really matter in which file you're storing the functions. That said, a directive is unlikely to be what you're looking for as a directive is mainly used to be linked to an html element like a widget. Think of it as the controller in the MVC model scheme. It where you can have interaction from/to the ui from the coding standing point. But you can't really call a directive function directly if you don't have access to a directive.
A service on the other hand is just a singleton object that can be injected in a controller or in other places.
What you want is probably this:
project.factory('draggable', function () {
function dragEnd($event) { ... }
return dragEnd
})
And inside your main module:
app.controller('mainController',
[
'$scope'
, '$http'
, '$cookies'
, '$cookieStore'
, '$location'
, 'draggable'
, function(
$scope
, $http
, $cookies
, $cookieStore
, $location
, draggable
) {
//here you can call draggable
}]
)
Here you can see that the draggable function aka dragEnd is injected in the controller. This is good if you want to use this common function for multiple handler but then you might need to bind the function to an object like this:
var draggable = draggable.bind(someobj)
Or use it with apply or call
draggable.call(someobj, event)
draggable.apply(someobj, [event])
The reason to do that is that if you want to acces this from within the function when it's called, it might not be what it you expect it to be depending on how you're actually calling the method.
Also one note regarding your directive... You always have to return something. In you case chances are that you created the factory but didn't return anything. For this reason you had the "undefined" error. If you don'T return anything the factory will create and delete the function when it's run.

Getting `state not defined` error when it is defined

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.

Conditionally inject angular module dependency

I'm new to angular and have the following code.
angular.module('MyApp')
.controller('loginController', ['$scope', '$http', 'conditionalDependency',
function ($scope, $http, conditionalDependency{
}
I would like to have conditionalDependency loaded conditionally. Something like this
if(true)
{
//add conditionalDependency
}
How can this be done. I've seen this post . However, my requirement is that I have the dependency specified in function
Thanks in advance.
Not quite clear as to why you would have to have it in a named function like in your example but...
If you need conditional dependencies, I would suggest taking a look at the following:
Conditional injection of a service in AngularJS
I've used this method in a couple niche scenarios and it works quite well.
EXAMPLE:
angular.module('myApp').controller('loginController',
['$injector', '$scope', '$http',
function($injector, $scope, $http) {
var service;
if (something) {
service = $injector.get('myService');
}
});
You can use it even without injecting injector in your controller
if(something){
var injector = angular.element(document).injector();
var myService = injector.get('myService')
}
Use:
angular.injector().get('conditionalDep');
You can inject $injector once to your file and call $injector.get('dep');

angularjs [ng:areq] Argument 'fn' is not a function, got string

I am new to angular js..I am getting follwing error please help me out
[ng:areq] Argument 'fn' is not a function, got string
var app = angular.module('demo',[]);
app.config('$routeProvider',function($routeProvider){
$routeProvider.when('/add',{
templateUrl:'demo/add.html',
controller:'addcontroller'
}).
when('/order',{
templateUrl:'demo/order.html',
controller:'ordercontroller'
});
});
app.controller('addcontroller',function($scope){
$scope.message="order";
});
app.controller('ordercontroller',function($scope){
$scope.message="order";
});
I think the error is in the config block, it should either be:
app.config(function($routeProvider){
// routeProvider config
});
or better:
app.config(['$routeProvider', function($routeProvider){
// routeProvider config, allows minification
}]);
the annotations are there for minification to work correctly. You can read more about it on AngularJS docs https://docs.angularjs.org/tutorial/step_05
Please note that this practice needs to be done throughout the app to work correctly.
Although not directly related to the context of this question, this error message can also be caused by a resolve block returning something else than a function, like this:
$stateProvider.state('mystate', {
url: "/myurl",
templateUrl: "mytemplate.html",
controller: "MyController",
resolve: {
authenticatedUser: securityAuthorizationProvider.requireAuthenticatedUser
}
});
if securityAuthorizationProvider.requireAuthenticatedUser happens to be undefined, you can get this error.
I know this is an older post, but thought I'd contribute what was wrong with my code with this exact error. I was injecting a service into my controller this way:
theApp.directive('theDirective', 'myService', ['$http', function ($http, myService) {}]);
Instead of this:
theApp.directive('theDirective', ['$http', 'myService', function ($http, myService) {}]);
Notice that my service was included outside of the inline array annotation! It was a boneheaded move on my part that cost me way too much time.
For the the problem was defining factory dependency outside the array. Most probably the minification was also an issue.
//Error in this
angular
.module('mymodule').factory('myFactory', 'thisconstant', function (thisconstant) {
});
This fixed by
//correct code
angular
.module('mymodule').factory('myFactory', ['thisconstant', function (thisconstant) {
}]);
Since there's been various use cases added here, I thought I'd also add mine. I got this error when re-formating a function service
angular
.app('myApp')
.service('MyService', function (){
// do something
return MyService;
})
into a class object:
export default class MyService { ... }
angular
.app('myApp')
.service('MyService', MyService);
My problem was that my service was returning itself at the end of the function and I needed to add a class function, which would do this:
export default class MyService {
constructor(){
// doing something
}
get() {
return MyService;
}
}
which fixed the issue for me. :)
I got this error by misunderstanding the way anonymous functions and named functions are treated in JavaScript.
This causes the error:
angular.module("app").factory("myDataService", ['$resource', myDataService]);
var myDataService = function($resource) {
return $resource('/url');
}
I should've either done this:
var myDataService = function($resource) {
return $resource('/url');
}
angular.module("app").factory("myDataService", ['$resource', myDataService]);
Or this:
angular.module("app").factory("myDataService", ['$resource', myDataService]);
function myDataService($resource) {
return $resource('/url');
}
More on the difference between anonymous function and named function here
In First line you need to use like this,
var app = angular.module('demo', ['ngRoute']);
and use the routing thing like this,
$routeProvider.when('/add').then({
templateUrl:'demo/add.html',
controller:'addcontroller'
});
Just try these steps once.

AngularJS - Error: Unknown provider: searchResultsProvider

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.

Resources