How to get service instance from module instance [Angular] - javascript

i have some module defined and services too with that module like below
var services=angular.module('app.services', []);
services.factory('ApiService', function($http,$cookies,UserService){
var dataFactory = {};
dataFactory.request=function(url,data,next){
return "Hi";
};
return dataFactory;
});
now in another script i can access module like
services=angular.module('app.services')
but how can i get service instance from that module like
apiService=angular.module('app.services').service('ApiService')

Edit:
after reading and understanding the author's comments, he was actually meant to block the entire app if the user is not permitted. his desired to do it by reusing the same code written in his ApiService factory.
--
You can 'hook' to app.run function which called before your controllers and you can utilize $window.location.href to relocate user to another page or site (if not permitted)
Iv'e updated this plunker with app.run entry
app.js
var app = angular.module('app', ['app.services']);
app.run(function(ApiService, $window) {
result = ApiService.request();
// This is where you check your permissions
var has_permissions = false;
// ...
if (!has_permissions) {
alert('being transferred to plnkr.co due to lack of permissions');
$window.location.href = 'http://plnkr.co/';
}
// Otherwise, continue normally
});
Original:
i made this plunker
if you separate all logic to api.services module, include it in your app
app.js
var app = angular.module('app', ['app.services']);
then you could use it by referencing the desired factory - ApiService
app.controller('myCtrl', ['$scope', 'ApiService',
function($scope, ApiService) {
$scope.result = ApiService.request();
}
]);
app.services.js
var services = angular.module('app.services', []);
services.factory('UserService', function() {
var UserService = {};
UserService.foo = function() {
return "foo";
};
return UserService;
});
services.factory('ApiService', function($http, UserService) {
var ApiService = {};
ApiService.request = function(url, data, next) {
return UserService.foo() + " Hi";
};
return ApiService;
});
plunker

Related

Utils class in Angular.js

I'd like to create an utility class in Angular.js that can be used by several controllers.
So far I created this:
'use strict';
angular
.module('App')
.factory('AppUtils', AppUtils);
function AppUtils() {
var vm = this;
vm.getPersonOf = getPersonOf;
function getPersonOf(personId, allPersons) {
var person = {};
person.personId = {personId: personId};
allPersons.forEach(function(p) {
if (p.personId === personId) {
person = p;
}
});
return person;
}
}
And I tried to use it in a controller like this:
'use strict';
angular
.module('App')
.controller('AppController', AppController);
function AppController(personId, allPersons, AppUtils) {
var vm = this;
vm.personId = personId;
vm.person = AppUtils.getPersonOf(vm.personId, allPersons);
...
}
But I get this:
PhantomJS 1.9.8 (Windows 7 0.0.0) App should dismiss modal FAILED
Error: [$injector:undef] Provider 'AppUtils' must return a value from $get factory method.
http://errors.angularjs.org/1.5.0/$injector/undef?p0=InvoiceUnitsUtils
(The real names have been renamed to make it easier.)
Why am I getting that error? Am I not declaring properly the Utility module?
The factory is in charge of creating a service and handing its instance to you. To do this, you need to return your utility class:
function AppUtils() {
return {
getPersonOf: getPersonOf
// pass other utility functions...
}
function getPersonOf(personId, allPersons) {
var person = {};
person.personId = {personId: personId};
allPersons.forEach(function(p) {
if (p.personId === personId) {
person = p;
}
});
return person;
}
}
I removed the vm part because we are handing a service which usually has no view model (the controller is in charge of that, service is more of a business logic expert).
Here's some more information about the $get function in Angular's providers:
https://docs.angularjs.org/guide/providers

use variable of another controller angularJS with ionic

I want to access variable from another controller any body help
My code
app.controller('MapCtrl',function($scope, $state, $cordovaGeolocation) {
$scope.search_item = function($event,item){
console.log(item);
var lat = item.lat;
var lng = item.lng;
}
});
to
app.controller("homeCtrl", function($scope,$http, $filter ){
});
You can set up a service that 'shares' the variable between the two controllers.
Create a file: services.js in the app/ directory (where app.js is located)
angular.module('app.services', [])
.service('var_transfer_service', function(){
var test_var;
return {
getVar: function () {
return test_var;
},
setVar: function( _test_var ) {
test_var = _test_var;
}
}
})
Now inject this service into the controllers that need variable sharing:
app.controller('MapCtrl',function($scope, $state, $cordovaGeolocation, var_transfer_service) {
$scope.search_item = function($event,item){
console.log(item);
var lat = item.lat;
var lng = item.lng;
var_transfer_service.setVar(lat);
}
});
app.controller("homeCtrl", function($scope,$http, $filter, var_transfer_service ){
var transferred_var = var_transfer_service.getVar();
// transferred_var will now equal 'lat' from the other controller
});
You can further modify the function definitions in services.js and function calls in your controllers to accommodate more variables.
Make sure to also add the services.js module to your app:
angular.module('app', ['ionic', 'app.controllers', 'app.services'])

Pass variables into AngularJS App

I am connecting to an API through a script (init.js) when starting my angular app. I then receive som information such as a username and a user ID that I want to define as global values to use in the AngularJS App.
How do I pass the variables on to use in the AngularJS app?
My thought now is to define the variables in the MainController to be able to use them anywhere.
init.js
(function () {
function appStart() {
//Get variables
var userId = 123;
var username = 'This is my name';
//Init Angular App
angular.bootstrap(document, ['myApp']); //How do I use the variables in the angular app?
}
function genericError() {
console.error('Something went wrong');
}
TT.native.init()
.done(appStart)
.fail(genericError);
})();
app.js
(function () { //Start
var app = angular.module('myApp', [
'myControllers',
'myDirectives',
'myFilters',
'myServices',
'ui.router'
]);
controller.js
var app = angular.module('myControllers', []);
app.controller('MainController', function ($scope, $state) {
$scope.userName = ""; //I want to use the variable from INIT.JS here
$scope.userId = 0; //I want to use the variable from INIT.JS here
});
The easiest solution would be:
var userId = -1;
var username = '';
(function () {
function appStart() {
//Get variables
userId = 123;
username = 'This is my name';
//Init Angular App
angular.bootstrap(document, ['myApp']); //How do I use the variables in the angular app?
}
function genericError() {
console.error('Something went wrong');
}
TT.native.init()
.done(appStart)
.fail(genericError);
})();
Then in the controller:
app.controller('MainController', function ($scope, $state) {
$scope.userName = userId;
$scope.userId = username;
});
But just know that this is not a good approach. You should connect to your api within the angular app. Maybe you should watch and read some tutorials before beginning to code...
You can use angular.module('myApp').value or angular.module('myApp').constant before bootstrapping angular. In your controller you should add variables into dependencies.
You probably using ngRouter or uiRouter so you could resolve the TT.native.init before entering the first route/state.

How to implement a controller trait in AngularJS

I want to give a set of controllers access to methods and properties defined in a trait. Right now the best implementation I have come up with is:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, CtrlTrait) {
$scope.name = CtrlTrait.presetName;
CtrlTrait.setGreeting.call($scope, 'Hello');
});
app.service('CtrlTrait', function() {
this.setGreeting = function(greeting) { this.greeting = greeting; }
this.presetName = 'tom';
});
Plunkr Code
This is fine, but I would like the properties and method to be accessible via the controller's $scope without having to manually create the alias in each controller. I want to be able to use the properties and method from the template just by having injected the service into the controller.
Is this possible, or do I have to create a [wrapper around]/[provider for] $scope like $specialCtrlScope that presets the properties and methods I want?
You can try using angular.extend like this: angular.extend($scope,CtrlTrait); It will allows us to use in the $scope the same functions that your service. So, you can use the function directly in your html like this:
<button ng-click="setGreeting('Good bye! ')">Good Bye</button>
Here is your plunker demo adapted:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, CtrlTrait) {
$scope.name = CtrlTrait.presetName;
// CtrlTrait.setGreeting.call($scope, 'Hello');
angular.extend($scope,CtrlTrait);
$scope.setGreeting('Hello World');
});
app.service('CtrlTrait', function() {
this.setGreeting = function(greeting) { this.greeting = greeting; }
this.presetName = 'tom';
});
http://plnkr.co/edit/BENS78mjFfpc6VCEtgK8?p=preview
You Can try the below in your controller
$scope.setGreeting = CtrlTrait.setGreeting
and can later use
$scope.setGreeting.call($scope, 'Hello');
EDIT AFTER THE COMMENT
Try this
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, CtrlTrait) {
$scope.trait = CtrlTrait;
$scope.name = $scope.trait.presetName;
$scope.trait.setGreeting.call($scope,'Hello');
});
app.service('CtrlTrait', function() {
var trait = {};
trait.setGreeting = function(greeting) { this.greeting = greeting; }
trait.presetName = 'tom';
return trait;
});
So I'll preface this with a disclaimer... I would not recommend that you actually do this, or at least not do it in this way. You're adding extra coupling between your controllers and services inside of a framework built around modularity and injection, all for the sake of saving a few method calls.
That said, here's a way to implement what you want. (JSFiddle here)
var app = angular.module('myApp', []);
var controllerMaker = function(trait,controllerCode){
return function($scope, $injector){
//'apply' traits to this scope
var apply = function(trait){
trait.applyTo($scope);
}
apply.$inject = [trait];
$injector.invoke(apply);
//Finishes the other injections
controllerCode.$inject = ['$scope'];
controllerCode($scope);
};
}
//Here's a sample 'trait'
app.service('CtrlTrait', function() {
this.applyTo = function(obj){
obj.setGreeting = function(greeting) { this.greeting = greeting; }
obj.presetName = 'tom';
}
});
//Then, setup your controller like this
app.controller('GreatController', controllerMaker("CtrlTrait",function($scope){ //Not using injection though!
$scope.bleh = $scope.presetName; //will be 'tom'
}))
There are certainly weaknesses with this, like how your controller loses injection, but if you reeeeeeally wanted to, I'm sure you could play aruond with $inject and find something that suits your needs.
Angular will inject the return value of a the function if it is an object. So in your code:
var app = angular.module('plunker', []);
app.controller('MainCtrl',["$scope","DefaultName","TraitService", function($scope, defaultName, traitService) {
$scope.name = defaultName;
$scope.OKPressed = function() {
traitService.setName($scope.name);
};
});
// You can use .constant() for a constant value;
app.constant("DefaultName", "tom");
app.service('TraitService', function() {
var traitService = {}; // The name does't matter
traitService.setName = function(name) {
// Not this.name = name because (this)is not guaranteed to persist or be the same across injections.
// I am only using local storage to illustrate. I usually use $rootScope to store
// Global variables. since they are always available on the $scope object without
// needing a service.
// That might be a better way for you ($rootScope)
localStorage.setItem("nameKey", name);
}
traitService.getName = function () {
return localStorage.getItem("nameKey");
}
return traitService; // This is what will be injected above
});

Inject dependencies in "run" method of the module in Angularjs

I trying to understand how do I work with Angularjs. It looks like nice framework, but I stuck with a little problem with DI...
How I can inject dependecies in "run" method of the module? I mean I able to do it, but it works only if I have service/factory/value with as same name as "run" parameter name.
I build a simple application do illustrate what I mean:
var CONFIGURATION = "Configuration"; //I would like to have App.Configuration
var LOG_SERVICE = "LogService"; //I would like to have App.Services.LogService
var LOGIN_CONTROLLER = "LoginController";
var App = {};
App.Services = {};
App.Controllers = {};
App = angular.extend(App, angular.module("App", [])
.run(function ($rootScope, $location, Configuration, LogService) {
//How to force LogService to be the logger in params?
//not var = logger = LogService :)
LogService.log("app run");
}));
//App.$inject = [CONFIGURATION, LOG_SERVICE]; /* NOT WORKS */
App.Services.LogService = function (config) {
this.log = function (message) {
config.hasConsole ? console.log(message) : alert(message);
};
};
App.Services.LogService.$inject = [CONFIGURATION];
App.service(LOG_SERVICE, App.Services.LogService);
App.Controllers.LoginController = function (config, logger) {
logger.log("Controller constructed");
}
//The line below, required only because of problem described
App.Controllers.LoginController.$inject = [CONFIGURATION, LOG_SERVICE];
App.factory(CONFIGURATION, function () { return { hasConsole: console && console.log }; });
Why I need it may you ask :) But in my mind, first off all to have meaningful namespaces to organize the code. It will also minimize name collision and in the last, when minifing the JS, the things breaks down, since it renamed to more shorten names.
I think that the reason
App.$inject = [CONFIGURATION, LOG_SERVICE];
doesn't work, is because you have 2 other parameters $rootScope & $location that you need to inject in the $inject. So it needs to be:
App.$inject = ["$rootScope", "$location", CONFIGURATION, LOG_SERVICE];
Another way you can inject your service is to use this version:
app.run(["$rootScope", "$location", CONFIGURATION, LOG_SERVICE,
function ($rootScope, $location, Configuration, LogService) {
}] );

Categories