Apologies for the code heavy post but I wanted to provide as much context as possible. I am having an issue with defining a service in my Angular.js application. Services are supposed to act as singletons throughout an application (source), so I am very confused to be getting the following behavior.
In my app.js file, I run my AmplitudeService Service and console.log(AmplitudeService). This outputs an object with all of the methods that I have defined within my AmplitudeService.js file. As such, I am able to properly use the service and log events as expected.
However, when I console.log(AmplitudeService) within my header.js, it outputs my Window object. As such, the Window does not contain functions such as "logEvent", "identifyUser", etc., so AmplitudeService is not usable in that case.
Would appreciate any and all insight!
AmplitudeService.js (source)
Note: If you check the author's syntax, he returns an object at the end of his service. In my research, I've read to use the "this" keyword when defining Service functions (source), and that you don't need to return an object as you would with a Factory, so I have updated it accordingly.
angular.module('AmplitudeService', [])
.service('AmplitudeService',
['$amplitude', '$rootScope', 'amplitudeApiKey', '$location',
function ($amplitude, $rootScope, amplitudeApiKey, $location) {
this.init = function() {
$amplitude.init(amplitudeApiKey, null);
$amplitude.logEvent('LAUNCHED_SITE', {page: $location.$$path});
}
this.identifyUser = function(userId, userProperties) {
$amplitude.setUserId(userId);
$amplitude.setUserProperties(userProperties);
}
this.logEvent = function(eventName, params) {
$amplitude.logEvent(eventName, params);
}
}]);
angular-amplitude.js (source)
This allows access to "$amplitude" throughout the application
(function(){
var module = angular.module('angular-amplitude', ['ng']);
module.provider('$amplitude', [function $amplitudeProvider() {
this.$get = ['$window', function($window) {
(function(e,t){
var r = e.amplitude || {};
var n = t.createElement("script");
n.type = "text/javascript";
n.async = true;
n.src = "https://d24n15hnbwhuhn.buttfront.net/libs/amplitude-2.2.0-min.gz.js";
var s = t.getElementsByTagName("script")[0];
s.parentNode.insertBefore(n,s);
r._q = [];
function a(e){
r[e] = function(){
r._q.push([e].concat(Array.prototype.slice.call(arguments,0)));
}
}
var i = ["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties"];
for(var o = 0; o < i.length; o++){
a(i[o])
}
e.amplitude = r
}
)(window,document);
return $window.amplitude;
}];
}]);
return module;
}());
App.js
angular.module('app', [
'ngRoute',
'angular-amplitude',
'AmplitudeService',
])
.run(['AmplitudeService', function(AmplitudeService){
console.log(AmplitudeService); // Outputs 'Object {}'
AmplitudeService.init();
AmplitudeService.logEvent('LAUNCHED_SITE');
console.log(AmplitudeService); // Outputs 'Object {}'
}])
Header.js
angular.module('app.common.header', [])
.controller('HeaderCtrl', [ '$rootScope', '$scope', '$location', '$scope', '$route', '$window', 'AmplitudeService', function($rootScope, $scope, $location, $route, $window, AmplitudeService){
$scope.goToSearch = function(term) {
$location.path('/search/' + term);
console.log(AmplitudeService); // Outputs 'Window {}'
};
}]);
Looks like you are injecting $scope in your controller, causing the unexpected mapping of the variable
angular.module('app.common.header', [])
.controller('HeaderCtrl', [ '$rootScope', '$scope', '$location', **'$scope'**, '$route', '$window', 'AmplitudeService', function($rootScope, $scope, $location, $route, $window, AmplitudeService){
$scope.goToSearch = function(term) {
$location.path('/search/' + term);
console.log(AmplitudeService); // Outputs 'Window {}'
};
}]);
as an aside if find this format far easier to read / work with when defining controllers
angular
.module('app.common.header', [])
.controller('HeaderCtrl', headerController);
headerController.$inject = [ '$rootScope', '$scope', '$location', '$route', '$window', 'AmplitudeService']
function headerController($rootScope, $scope, $location, $route, $window, AmplitudeService){
$scope.goToSearch = function(term) {
$location.path('/search/' + term);
console.log(AmplitudeService); // Outputs 'Window {}'
};
}
Related
hi all i using angular js i need to transfer the value from one page controller to another page controller and get that value into an a scope anybody help how to do this
code Page1.html
var app = angular.module("app", ["xeditable", "angularUtils.directives.dirPagination", "ngNotify", "ngCookies","ngRoute"]);
app.controller('Controller1', ['$scope', '$http', '$window', '$filter','$notify','$cookieStore',
function ($scope, $http, $window, $filter, $notify, $cookieStore)
{
$scope.Message="Hi welcome"
}]);
now i want to show scope message into page2 controller
var app = angular.module("app", ["xeditable", "angularUtils.directives.dirPagination", "ngNotify", "ngCookies","ngRoute"]);
app.controller('Controller2', ['$scope', '$http', '$window', '$filter','$notify','$cookieStore',
function ($scope, $http, $window, $filter, $notify, $cookieStore)
{
///here i want get that scope value
}]);
You can use $rootScope instead of $scope:
// do not forget to inject $rootScope as dependency
$rootScope.Message="Hi welcome";
But the best practice is using a service and share data and use it in any controller you want.
You should define a service and write getter/setter functions on this.
angular.module('app').service('msgService', function () {
var message;
this.setMsg = function (msg) {
message = msg;
};
this.getMsg = function () {
return message;
};
});
Now you should use the setMeg function in Controller1 and getMsg function in Controller2 after injecting the dependency like this.
app.controller('Controller1', ['$scope', '$http', '$window', '$filter','$notify','$cookieStore', 'msgService',
function ($scope, $http, $window, $filter, $notify, $cookieStore, msgService)
{
$scope.Message="Hi welcome"
msgService.setMsg($scope.Message);
}]);
app.controller('Controller2', ['$scope', '$http', '$window', '$filter','$notify','$cookieStore', 'msgService',
function ($scope, $http, $window, $filter, $notify, $cookieStore, msgService)
{
///here i want get that scope value
console.log('message from contoller 1 is : ', msgService.getMsg());
}]);
You should use services for it .
Services
app.factory('myService', function() {
var message= [];
return {
set: set,
get: get
}
function set(mes) {
message.push(mes)
}
function get() {
return message;
}
});
And in ctrl
ctrl1
$scope.message1= 'Hi';
myService.set($scope.message1);
ctrl2
var message = myService.get()
Sharing data from one controller to another using service
We can create a service to set and get the data between the controllers and then inject that service in the controller function where we want to use it.
Service :
app.service('setGetData', function() {
var data = '';
getData: function() { return data; },
setData: function(requestData) { data = requestData; }
});
Controllers :
app.controller('Controller1', ['setGetData',function(setGetData) {
// To set the data from the one controller
$scope.Message="Hi welcome";
setGetData.setData($scope.Message);
}]);
app.controller('Controller2', ['setGetData',function(setGetData) {
// To get the data from the another controller
var res = setGetData.getData();
console.log(res); // Hi welcome
}]);
Here, we can see that Controller1 is used for setting the data and Controller2 is used for getting the data. So, we can share the data from one controller to another controller like this.
Hi I am new to angularjs and I am trying to inject some factory to controller but I am facing difficulties. My factory works fine. I am able to set data in factory.
Below is my code where I inject factory.
function () {
angular.module('RoslpApp').controller('RegistrationOTPVerification', ['$scope', '$http', '$translatePartialLoader', '$translate', '$state', '$stateParams', 'SomeFactory',
function ($scope, $http, $translatePartialLoader, $translate, $state, $stateParams, CONSTANTS, SomeFactory) {
var OTP = $stateParams.pageList.OTP;
$scope.EnterOTP = "Please enter this OTP to verify the user " + OTP;
//RegistrationOTPVerification.$inject = ['SomeFactory'];
//Facing issues in above line
alert(1);
function RegistrationOTPVerification(SomeFactory) {
var vm = this;
vm.someVariable = SomeFactory.getData();
console.log(vm.someVariable); // logs your data
alert(vm.someVariable);
}
});
This is my factory code.
(function () {
'use strict';
angular
.module('RoslpApp')
.factory('SomeFactory', SomeFactory);
SomeFactory.$inject = [];
function SomeFactory() {
var someData;
var factory = {
setData: setData,
getData: getData
};
function setData(data) {
someData = data;
}
function getData() {
return someData;
}
return factory;
}
})();
I set data in some other controller with SomeFactory.setData("123")
I want to inject someFactory as below:
RegistrationOTPVerification.$inject = ['SomeFactory'];
But whenever I write this, I get error RegistrationOTPVerification is undefined. If I comment that line everything works fine but I want to get some data from factory.
My factory name is SomeFactory and I want to inject in above controller. Any help would be appreciated.
Firstly, you missed CONSTANTS in your injections.
Next, I think you are mixing two kinds of syntax for controller here. Either use anonymous function or named. Don't mix both together.
Here's how your code should look like.
function () {
angular.module('RoslpApp').controller('RegistrationOTPVerification', ['$scope', '$http', '$translatePartialLoader', '$translate', '$state', '$stateParams', 'SomeFactory',
function ($scope, $http, $translatePartialLoader, $translate, $state, $stateParams, SomeFactory) {
var vm = this;
var OTP = $stateParams.pageList.OTP;
vm.EnterOTP = "Please enter this OTP to verify the user " + OTP;
vm.someVariable = SomeFactory.getData();
console.log(vm.someVariable); // logs your data
alert(vm.someVariable);
});
You missed CONSTANTS in controller dependency list:
'$translate', '$state', '$stateParams', 'SomeFactory',
... $translate, $state, $stateParams, CONSTANTS, SomeFactory) {
So whatever you inject SomeFactory is available in controller under the name CONSTANTS and symbol SomeFactory is undefined.
i'm a new in Angular. I try create factory but got an Error: AuthFactory.getUserInfo is not a function. Could somebody help me?
My Code:
auth.factory.js:
angular.module('tsg').factory('AuthFactory', function() {
return {
getUserInfo: function getUserInfo(){
console.log("AuthFactory.getUserInfo()");
return "userInfo";
}
};
});
header.js:
angular.module('tsg').controller('HeaderCtrl',HeaderCtrl);
HeaderCtrl.$inject = ['$scope', '$rootScope', '$location','$cookieStore','AuthFactory'];
function HeaderCtrl($scope, $cookieStore, AuthFactory)
{
AuthFactory.getUserInfo();
$scope.username = "UserName123";
$scope.date = new Date();
};
When you do a DI , their sequence really matters
HeaderCtrl.$inject = ['$scope', '$rootScope', '$location','$cookieStore','AuthFactory'];
function HeaderCtrl($scope, $cookieStore, AuthFactory)
the sequence of parameters is incorrect.
HeaderCtrl.$inject = ['$scope', '$rootScope', '$location','$cookieStore','AuthFactory'];
function HeaderCtrl($scope, $cookieStore, AuthFactory)
in your case AuthFactory instance inside your controller is not the factory you have written. It is the instance of $location service. You have misplaced it in the injection sequence.
When you do dependency injection follow the correct order of it as follows:
HeaderCtrl.$inject = ['$scope', '$rootScope', '$location','$cookieStore','AuthFactory'];
function HeaderCtrl($scope, $rootScope,$location,$cookieStore, AuthFactory)
now you factory will work as you expected.
Hi I have created two angulerjs files for same ng-app example.
admin.js
var app = angular.module('arcadminmodule', ['ngTable', 'ui-notification']);
app.controller('ArcAdminController', ['$http', '$scope', '$filter', '$interval', 'ngTableParams', 'Notification', function($http, $scope, $filter, $interval, ngTableParams, Notification) {});
admin1.js
var app = angular.module('arcadminmodule');
app.controller('ArcAdminController', ['$http', '$scope', '$filter', '$interval', 'ngTableParams', 'Notification', function($http, $scope, $filter, $interval, ngTableParams, Notification) {});
But its overriding admin.js from admin1.js
please help me out....
In admin1.js when you write:
var app = angular.module('arcadminmodule');
you are not creating a new module. You are trying to get an existing module named 'arcadminmodule'.. If you want to create a new module, you will have to write something like this:
var app = angular.module('arcadminmodule',[]); // add your depencencies...
Now, In your case, in admin.js you are creating your module and admin1,js you are making use of the same module. In angular you cannot have two controllers with the same name. Controllers are for (from the docs):
Set up the initial state of the $scope object.
Add behavior to the $scope object.
So If you need are trying to apply some roles or some business logic, It need to go into one controller. Make sure your controller contain only the business logic needed for a single view.
I think its no need for use the same controller in two places.But you can use services in places.If you need to do some think different from the ArcAdminController,use this structure.
Services
-service1.js
(function (angular) {
angular.module('marineControllers').service('boatService', function (ajaxService) {
}
)
-service2.js
-module..js
var artistControllers = angular.module('marineControllers',['ngAnimate']);
Controllers
-controller1
(function (angular) {
angular.module('marineControllers').controller("BoatController", ['$scope', '$http', '$routeParams',
'dashboardService', '$filter', 'loginService', '$location', 'boatService', 'autocompleteFactory', 'utilityFactory',
function ($scope, $http, $routeParams, dashboardService, $filter, loginService, $location, boatService, autocompleteFactory, utilityFactory) {
function loadAllFishingBoat() {
$scope.boatsTable.length = 0;
if (!$scope.$$phase)
$scope.$apply();
boatService.getAllBoatAndDevice().then(function (data) {
$scope.boatsTable = data;
if (!$scope.$$phase)
$scope.$apply();
});
};
}]);
})(angular);
-controller2
(function (angular) {
angular.module('marineControllers').controller("DeviceController", ['$scope', '$http', '$routeParams',
'dashboardService', '$filter', 'loginService', '$location', 'deviceService', 'autocompleteFactory', 'utilityFactory','commonDataService',
function ($scope, $http, $routeParams, dashboardService, $filter, loginService, $location, deviceService, autocompleteFactory, utilityFactory,commonDataService) {
function loadAllFishingBoat() {
$scope.boatsTable.length = 0;
if (!$scope.$$phase)
$scope.$apply();
boatService.getAllBoatAndDevice().then(function (data) {
$scope.boatsTable = data;
if (!$scope.$$phase)
$scope.$apply();
});
};
}]);
})(angular);
I have been use many services in both controllers,still they are different logics.
I'm setting a rootScope variable to maintain the state of the program. This works, but I don't think it's quite 'right'. Is there a better way to select an object from an array?
Here's my current code.
angular.module('myApp.controllers', [])
.controller('packingCtrl', ['$scope', '$http', '$filter', '$rootScope', function($scope, $http, $filter, $rootScope) {
$http.get('data/trayData.json').success(function(data) {
$scope.trays = data;
});
var currentOrder = $rootScope.currentlyPacking;;
$http.get('data/orderData.json').success(function(data) {
$scope.orders = data;
$scope.current = $filter('filter')($scope.orders, {orderId: currentOrder});
});
}])
Thanks in advance for any insight / best practices.
You can create a service to hold your state. Each service instance is a singleton, so when the service is injected into various controllers, all will see the same state.
var currentlyPackingSvc = function($http) {
var currentlyPacking = {
}
return {
currentlyPacking: currentlyPacking,
getTrays: function() { /* make $http call and update currentlyPacking */ },
getOrders: function() { /* make $http call and update currentlyPacking */ }
}
}
angular.service('currentlyPackingSvc', ['$http', currentlyPackingSvc]);
angular.controller('packingCtrl', ['$scope', '$http', '$filter', '$rootScope', 'currentlyPackingSvc'
function($scope, $http, $filter, $rootScope, currentlyPackingSvc) {
...
var currentOrder = currentlyPackingSvc.currentlyPacking;
...
}]);
Assuming you leave your 'currentlyPacking' property as an object, the changes should automatically be pushed to your scope.
This way, you have all your state isolated to one service that can be utilized anywhere.