In my main controller I have a user service that returns the current user.
// Curr user
userService.getCurrentUser().then(user => {
mainCtrl.currUser = user;
});
Is there any way to be able to use the currUser variable in other controllers without injecting my service and calling this method over and over again in maybe 50 controllers?
Ex.
// My other awesome controller
console.log(currUser.fullName);
You could go for a LocalStorage or $rootScope. , if you are sure about not using Providers/Services
Sample:
myApp.controller('DemoController1', ['$scope', '$rootScope', function DemoController($scope,$rootScope) {
$rootScope.currUser.fullName ="test";
}]);
Then access it as,
myApp.controller('DemoController2', ['$scope', '$rootScope', function DemoController($scope,$rootScope) {
var fullName = $rootScope.currUser.fullName;
}])
you can use $rootScope like bellow:
mainCtrl.$rootScope.currUser = user;
and the other controller, you can recover this as bellow:
console.log(yourContrl.$rootScope.currUser.fullName);
You don't want you use controller injections? Use injector its the same like injections but also different :D ... like in this runnable fiddle demo. In that way you still can use services, factories, or components.
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function ($scope) {
$scope.name = angular.injector(['data']).get('user').currUser.username;
});
angular.module('data', []).factory('user', function () {
return {
currUser: {
username: 'Alfred'
}
}
});
Related
How do I use services to store variables so that I can access it in previous controller on pressing back button?
For example:
.controller('myCtrl', function($scope, myservice) {
console.log(myservice.myvar.myval)
// output: undefined pressing back button
});
.controller('myCtrl2', function($scope, myservice) {
myservice.myvar.myval = "This I want in controller myCtrl on pressing back button"
console.log(myservice.myvar.myval)
// outputs the value
});
If services are not the best approach and I should use $rootScopethen will it do the job.
P.S angular.module and myservice are defined.
You need to use getter-setter for this.
For Example:
angular.module('MyModule', [])
.service('myservice', function () {
this.myval = "value";
this.getValue = function () { return this.myval }; //getter
this.setValue = function (val) { this.myval = val }; //setter
})
.controller('myCtrl', function($scope, myservice) {
console.log(myservice.getValue());
// get the value here
});
.controller('myCtrl2', function($scope, myservice) {
myservice.setValue("This I want in controller myCtrl on pressing back button");
// Set the value here
});
This is for the reference only. Please don't copy-paste and run code.
Angular services are singletons and can be freely shared among components, which have access to dependency injection. You can define a closure with a module pattern of getters and setters or directly attach properties to the object you intend to return.
I see 4 options, you can store it in a service, in $rootScope, in localStorage for persistent storage, and in sessionStorage to store datas only during the application lifetime. There's btw a nice module that wrap localStorage and sessionStorage, and make its use simpler :
http://ngmodules.org/modules/ngStorage
I don't know what it is about injecting factories, but I am having the most difficult time.
I've simulated what I'm attempting to do via this sample plunk http://plnkr.co/edit/I6MJRx?p=preview, which creates a kendo treelist - it works fine.
I have an onChange event in script.js which just writes to the console. That's also working.
My plunk loads the following:
1) Inits the app module, and creates the main controller myCtrl (script.js)
2) Injects widgetLinkingFactory int myCtrl
3) Injects MyService into widgetLinkingFactory
The order in which I load the files in index.html appears to be VERY important.
Again, the above plunk is NOT the real application. It demonstrates how I'm injecting factories and services.
My actual code is giving me grief. I'm having much trouble inject factories/services into other factories.
For example,
when debugging inside function linking() below, I can see neither 'CalculatorService' nor 'MyService' services. However, I can see the 'reportsContext' service.
(function () {
// ******************************
// Factory: 'widgetLinkingFactory'
// ******************************
'use strict';
app.factory('widgetLinkingFactory', ['reportsContext', 'MyService', linking]);
function linking(reportsContext, MyService) {
var service = {
linkCharts: linkCharts
};
return service;
function linkCharts(parId, widgets, parentWidgetData) {
// *** WHEN DEBUGGING HERE, ***
// I CANNOT SEE 'CalculatorService' AND 'MyService'
// HOWEVER I CAN SEE 'reportsContext'
if (parentWidgetData.parentObj === undefined) {
// user clicked on root node of grid/treelist
}
_.each(widgets, function (wid) {
if (wid.dataModelOptions.linkedParentWidget) {
// REFRESH HERE...
}
});
}
}
})();
A snippet of reportsContext'service :
(function () {
'use strict';
var app = angular.module('rage');
app.service('reportsContext', ['$http', reportsContext]);
function reportsContext($http) {
this.encodeRageURL = function (sourceURL) {
var encodedURL = sourceURL.replace(/ /g, "%20");
encodedURL = encodedURL.replace(/</g, "%3C");
encodedURL = encodedURL.replace(/>/g, "%3E");
return encodedURL;
}
// SAVE CHART DATA TO LOCAL CACHE
this.saveChartCategoryAxisToLocalStorage = function (data) {
window.localStorage.setItem("chartCategoryAxis", JSON.stringify(data));
}
}
})();
One other point is that in my main directive code, I can a $broadcast event which calls the WidgetLinking factory :
Notice how I'm passing in the widgetLinkingFactory in scope.$on. Is this a problem ?
// Called from my DataModel factory :
$rootScope.$broadcast('refreshLinkedWidgets', id, widgetLinkingFactory, dataModelOptions);
// Watcher setup in my directive code :
scope.$on('refreshLinkedWidgets', function (event, parentWidgetId, widgetLinkingFactory, dataModelOptions) {
widgetLinkingFactory.linkCharts(parentWidgetId, scope.widgets, dataModelOptions);
});
I am wasting a lot of time with these injections, and it's driving me crazy.
Thanks ahead of time for your assistance.
regards,
Bob
I think you might want to read up on factories/services, but the following will work:
var app = angular.module('rage')
app.factory('hi', [function(){
var service = {};
service.sayHi = function(){return 'hi'}
return service;
}];
app.factory('bye', [function(){
var service = {};
service.sayBye = function(){return 'bye'}
return service;
}];
app.factory('combine', ['hi', 'bye', function(hi, bye){
var service = {};
service.sayHi = hi.sayHi;
service.sayBye = bye.sayBye;
return service;
}];
And in controller...
app.controller('test', ['combine', function(combine){
console.log(combine.sayHi());
console.log(combine.sayBye());
}];
So it would be most helpful if you created a plunk or something where we could fork your code and test a fix. Looking over your services it doen't seem that they are returning anything. I typically set up all of my services using the "factory" method as shown below
var app = angular.module('Bret.ApiM', ['ngRoute', 'angularFileUpload']);
app.factory('Bret.Api', ['$http', function ($http: ng.IHttpService) {
var adminService = new Bret.Api($http);
return adminService;
}]);
As you can see I give it a name and define what services it needs and then I create an object that is my service and return it to be consumed by something else. The above syntax is TypeScript which plays very nice with Angular as that is what the Angular team uses.
I am New to Angular Js.
Is It Possible to Forward Scope of the RestaurantController to MenuController Code as Follows
Example :-
angular.module('restaurants').controller('RestaurantController', ['$scope',
function($scope) {
$scope.restaurantid="435scvcxvbrcvbnvn";
}
]);
And i assigned restaurant id as New scope in Menu Controller as Follows
angular.module('menus').controller('MenuController', ['$scope',
function($scope) {
$scope.currentrestaurantid= $scope.restaurantid;
alert($scope.currentrestaurantid); // showing Null
}
]);
The Restaurant Id is not Persisted .. Honestly i feel that some thing is Missing .
How to Get the Id From Restaurant controller to Menu Controller ?
Try inheritance
angular.module('restaurants', []);
angular.module('menus', ['restaurants']);
angular.module('restaurants').controller('RestaurantController', function($scope) {
$scope.restaurantid="435scvcxvbrcvbnvn";
});
angular.module('menus').controller('MenuController', ['$scope','$controller',
function($scope, $controller) {
$controller('RestaurantController', {$scope: $scope});
$scope.currentrestaurantid= $scope.restaurantid;
}
]);
Working fiddle
I propose use the rootScope to do that.
Use the $broadcast to notify the other controller the change on the firsts controller scope.
$rootScope.$broadcast("restIDUpdated", {
restaurant: $scope.restaurantid
});
Use the $on to receive the notification in the second controller about the event that happend in the first controller.
$scope.$on("restIDUpdated", function (event, args) {
$scope.restaurant = args.restaurant;
});
There is an example of this here
Try something like this.
angular.module('restaurants').controller('RestaurantController', function($scope) {
$rootScope.$broadcast("restIDUpdated", {
restaurantid: 435scvcxvbrcvbnvn
});
});
angular.module('menus').controller('MenuController', ['$scope','$controller',
function($scope, $controller) {
$controller('RestaurantController', {$scope: $scope});
$scope.$on("restIDUpdated", function (event, args) {
$scope.currentrestaurantid= args.restaurantid;
});
}
]);
But to be honest I am not sure if this mechanism works with two different angular apps, I know using the same module it works but not sure what is going to happen using two different modules, but take a look at the API
A pattern I commonly use is to create an angular service and inject it into controllers I want to share data with. something like this...
angular.module('restaurants', []);
angular.module('menus', ['restaurants']);
angular.module('restaurants').service('RestaurantService', function() {
this.restaurantid = "435scvcxvbrcvbnvn";
});
angular.module('restaurants').controller('RestaurantController', function($scope, RestaurantService) {
$scope.restaurantid = RestaurantService.restaurantid;
});
angular.module('menus').controller('MenuController', function($scope, $controller, RestaurantService) {
$scope.currentrestaurantid = RestaurantService.restaurantid;
});
As said here, injectable service as generic way for your situation.
But I'd like to point more pretty way, using markup and controller as (docs) expression.
For example you have following controller:
.controller('RestaurantController', function($scope) {
$scope.restaurantid="435scvcxvbrcvbnvn";
})
and you can bind it to variable in the scope:
<div ng-controller="RestaurantController as restaurant">
<div ng-controller="MenuControllerOrAnyOther">
restaurant id = {{restaurant.restaurantid}}
</div>
</div>
Remarks
This approach would be nicer if you need restaurantid ONLY in markup, e.g.
<button ng-click="select(restaurant.restaurantid)">
This looks ugly, if you want to use restaurantid in js code (you should use injectable services then):
var restaurantid = $scope.$eval('restaurant.restaurantid');
I'm trying to move some generic navigation formatting code from the controller into a factory.
Do I need to inject $scope into my factory? I've tried six ways from Sunday to inject $scope, but every method I've tried gives me errors.
Or do my stagesHeight, stagesWidth variables in the factory need scoping at all?
controller:
angular.module('sysomos.ads').
controller('LinkController', ['$scope', '$state', '$api', 'LinkFactory',
function($scope, $state, $api, LinkFactory) {
console.log(LinkFactory.make(['twitter', 'ad', 'view']));
}
]);
factory:
angular.module('sysomos.ads').
factory('LinkFactory', function(){
return {
make: function(arrSteps){
$scope.stagesHeight = 30;// what scope does my logic need?
$scope.stagesWidth = 145;
// lots of intervening steps
return arrSteps.join(",");// just return me the array for now
};
}
]);
Try something like this:
.factory('LinkFactory', function(){
return {
make: function(arrSteps){
var stagesHeight = 30;// what scope does my logic need?
var stagesWidth = 145;
// lots of intervening steps
return arrSteps.join(",");// just return me the array for now
};
}
Then call your service/factory from your ctrl like this:
$scope.foo.something = LinkFactory.make();
I hope this helps.
I've created an angular app that has the following structure.
Application configuration, routes, directives, controllers and filters are all defined in index.js (I know this is not recommended). All of my general functions are in a controller called main.js, this is also the controller I am using in my main view in index.html. From then on the app consists of 10 different views, each has it's own controller.
main.js has become very difficult to maintain, so I would like to separate it into five external "utility" style files that contain the general function the application uses. These functions all use angular's $scope and must be able to be accessed by all the views and controllers that exist in the application.
For the past few days I've tried several different methods, such as defining the functions under angular's factory service, using angular's $provide method, defining a controller without a view and many others. None of them worked for me. What is the simplest way to separate the functions that exist in main.js to external js files without changing any code within the functions themselves. Let's pretend that the function cannot be turned into a directive.
Example -
Function that checks users name for 'guest' string and returns an image
main.js -
$scope.defaultpic = function(username) {
var guest = username;
if (guest.indexOf("guest") != -1){
{return {"background-image": "url('data:image/png;base64,chars"}}
}
}
in the view
<img ng-style="defaultpic(JSON.Value)" class="user_pic" ng-src="getprofilepic/{{JSON.Value}}"/>
Cheers,
Gidon
In order to use the function in markup, you still have to bind it to the scope. But, you can move the body of the function to a service:
angular.module('myapp').factory('picService',[ function () {
return {
defaultpic: function(username) {
var guest = username;
if (guest.indexOf("guest") != -1){
{return {"background-image": "url('data:image/png;base64,chars"}}
}
}
};
}]);
And then bind it up in the controller:
$scope.defaultpic = picService.defaultpic;
Refactor controller functions as services declared in different files
As you correctly stated, a great approach to refactor the functions is to put them into different services.
According to the angular Service docs:
Angular services are singletons objects or functions that carry out specific tasks common to web apps.
Here is an example:
Original code
Here we have a simple Hello World app, with a controller that has two functions: greet() and getName().
app.js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.getName = function () {
return 'World';
}
$scope.greet = function (name) {
return 'Hello ' + name;
};
});
index.html
...
<div id="container" ng-controller="MainCtrl">
<h1>{{greet(getName())}}</h1>
</div>
...
We want to test that our scope always has both functions, so we know it is working as intended, so we are going to write two simple jasmine tests:
appSpec.js
describe('Testing a Hello World controller', function() {
var $scope = null;
var ctrl = null;
//you need to indicate your module in a test
beforeEach(module('plunker'));
beforeEach(inject(function($rootScope, $controller) {
$scope = $rootScope.$new();
ctrl = $controller('MainCtrl', {
$scope: $scope
});
}));
it('should say hallo to the World', function() {
expect($scope.getName()).toEqual('World');
});
it('shuld greet the correct person', function () {
expect($scope.greet('Jon Snow')).toEqual('Hello Jon Snow');
})
});
Check it out in plnkr
Step 1: Refactor controller functions into separate functions
In order to start decoupling our controller to our functions we are going to make two individual functions inside app.js.
app.js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.getName = getName;
$scope.greet = greet;
});
function getName() {
return 'World';
}
function greet(name) {
return 'Hello ' + name;
}
Now we check our test output and we see that everything is working perfectly.
Check out the plnkr for step 1
Step 2: Move functions to their own services
We will define a NameService and GreetService, put our functions in them and then define the services as dependencies in our controller.
app.js
var app = angular.module('plunker', []);
app.service('NameService', function () {
this.getName = function getName() {
return 'World';
};
});
app.service('GreetService', function() {
this.greet = function greet(name) {
return 'Hello ' + name;
}
});
app.controller('MainCtrl', ['$scope', 'NameService', 'GreetService', function($scope, NameService, GreetService) {
$scope.getName = NameService.getName;
$scope.greet = GreetService.greet;
}]);
We make sure that our tests are still green, so we can move on to the final step.
Have a look at step 2 in plunker
Final Step: Put our services in different files
Finally we will make two files, NameService.js and GreetService.js and put our services in them.
NameService.js
angular.module('plunker').service('NameService', function () {
this.getName = function getName() {
return 'World';
};
});
GreetService.js
angular.module('plunker').service('GreetService', function() {
this.greet = function greet(name) {
return 'Hello ' + name;
}
});
We also need to make sure to add the new scripts to our index.html
index.html
...
<script src="NameService.js"></script>
<script src="GreetService.js"></script>
...
This is how our controller looks like now, neat huh?
app.js
var app = angular.module('plunker', []);
app.controller('MainCtrl', ['$scope', 'NameService', 'GreetService', function($scope, NameService, GreetService) {
$scope.getName = NameService.getName;
$scope.greet = GreetService.greet;
}]);
Plunker for the final step.
And that's it! Our tests still pass, so we know everything works like a charm.