I created a common service to share the data between controller.
Below is the code snippet.
Here am getting undefined while using setter and getter. While accessing the object directly am getting the value. How to get the values using getter and setter.
what happens behind the scenes here.
// JavaScript source code
(function () {
'use strict';
angular.module('app',[])
})();
(function () {
'use strict';
angular
.module('app')
.factory('appcontext', appContext);
function appContext() {
var service = {
getStartDate: getStartDate,
setStartTime : setStartTime,
startTime : startTime
};
return service;
//private variables
var startTime = '';
function setStartTime(startTime) {
startTime = startTime;
}
function getStartDate() {
return startTime;
}
}
})();
(function () {
'use strict';
angular.module('app')
.controller("InsController", InsController)
InsController.$inject = ['appcontext'];
function InsController(appcontext) {
appcontext.setStartTime(new Date());
console.log(appcontext.getStartDate()); // undefined
appcontext.startTime = new Date();
console.log(appcontext.startTime); //prints the date correctly
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html ng-App="app">
<div ng-controller= "InsController">
<div>{{ }}</div>
</div>
</html>
There is nothing wrong with your code. It is just the naming convention that is causing the conflict if I just replace your setStartTime method parameter name. Everything works well.
// JavaScript source code
(function () {
'use strict';
angular.module('app',[])
})();
(function () {
'use strict';
angular
.module('app')
.factory('appcontext', appContext);
function appContext() {
var service = {
getStartDate: getStartDate,
setStartTime : setStartTime,
startTime : startTime
};
return service;
var startTime = '';
function setStartTime(newStartTime) {
startTime = newStartTime;
}
function getStartDate() {
return startTime;
}
}
})();
(function () {
'use strict';
angular.module('app')
.controller("InsController", InsController)
InsController.$inject = ['appcontext'];
function InsController(appcontext) {
appcontext.setStartTime(new Date());
console.log(appcontext.getStartDate());
appcontext.startTime = new Date();
console.log(appcontext.startTime); //prints the date correctly
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html ng-App="app">
<div ng-controller= "InsController">
<div>{{ }}</div>
</div>
</html>
You need to eliminate the startTime variable and reference is as service.startTime. You've created a property for it on your service, but the rest of your code references the var rather than the property.
function setStartTime(startTime) {
service.startTime = startTime;
}
function getStartDate() {
return service.startTime;
}
Not sure if this is all your code, but it looks like some of the uses of StartDate should be StartTime as well.
My this blog post may help you :
http://www.infragistics.com/community/blogs/dhananjay_kumar/archive/2015/05/04/how-to-share-data-between-controllers-in-the-angularjs.aspx
Just return the functions you would like to expose. Since you have your getter and setter functions, don't return the variable itself, that wouldn't be much of a help. Create a variable service which stores every internal stuff you need and your functions should make use of that.
// JavaScript source code
(function () {
'use strict';
angular.module('app',[])
})();
(function () {
'use strict';
angular
.module('app')
.factory('appcontext', appContext);
function appContext() {
var service = this;
return {
getStartDate: getStartDate,
setStartTime : setStartTime
};
//private variables
service.startTime = '';
function setStartTime(startTime) {
service.startTime = startTime;
}
function getStartDate() {
return service.startTime;
}
}
})();
(function () {
'use strict';
angular.module('app')
.controller("InsController", InsController)
InsController.$inject = ['appcontext'];
function InsController(appcontext) {
appcontext.setStartTime(new Date());
console.log(appcontext.getStartDate()); // undefined
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html ng-App="app">
<div ng-controller= "InsController">
<div>{{ }}</div>
</div>
</html>
Related
I'm using angularjs and I am trying to parse a value from a service to my $scope controller. The problem is that is loading first the $scope and then the service. As a result me my scope is always undefinied. I tried many solutions that I found by no-one is worked for me. Can anyone help me please?
My service:
'use strict';
angular.module('myApp')
.service('getCategoriesService', function ($rootScope) {
getCategories = function () {
var categoriesByLocation = 1;
return categoriesByLocation;
};
and my controller:
angular.module("myApp")
.controller('MyCtrl', function ($scope,getCategoriesService) {
$scope.resultCategory = getCategoriesService.getCategories();
});
Use the this. when declaring a function in a service.
.service('getCategoriesService', function ($rootScope) {
this.getCategories = function () {
var categoriesByLocation = 1;
return categoriesByLocation;
};
})
demo
var app = angular.module("myApp",[]);
app.controller('MyCtrl', function ($scope,getCategoriesService) {
$scope.resultCategory = getCategoriesService.getCategories();
});
app.service('getCategoriesService', function ($rootScope) {
this.getCategories = function () {
var categoriesByLocation = 1;
return categoriesByLocation;
};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
{{resultCategory}}
</div>
Change it as
angular.module("myApp")
.controller('MyCtrl', function ($scope,getCategoriesService) {
getCategoriesService.getCategories().then((function (d) {
$scope.resultCategory = d;
}
});
I'm trying to get a service instance but am getting an error. I am getting the exception that Calculator.random() is not a function. Any idea what I'm doing wrong?
angular
.module('app')
.factory('Calculator',function(){
var random = {};
random.number = function (){
return Math.random();
};
return random;
});
angular
.module('app')
.controller('homeCtrl', ['$scope','Calculator', function ($scope,Calculator) {
$scope.random = Calculator.random();
}]);
You can try like this:
angular
.module('app').controller('homeCtrl', function($scope, Calculator) {
$scope.random=Calculator.number();//in your factory number holds the random function.
}
IN your case its breaking
reason: Calculator.random(); is not a function.
Like Cyril said, you define an object with a local name random in the calculator factory definition. You then return that object but that object has a property called number that points to a function not a property called random.
angular
.module('app', [])
.factory('Calculator',function(){
var random = {};
random.number = function (){
return Math.random();
};
return random;
});
angular
.module('app')
.controller('homeCtrl', ['$scope','Calculator', function ($scope,Calculator) {
$scope.random = Calculator.number();
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="homeCtrl">{{random}}</div>
</div>
This should work:
angular
.module('app', [])
.factory('Calculator', function () {
return function () {
return Math.random();
}
});`
In angularjs,I use the directive to contains the subpage into mainpage.
However, I found when I want to call the JS function in subpage, the browser always return back the information .
I wonder what can I do to fixed the errors.
Mainpage
var menuModule = angular.module('menuModule',[]);
menuModule.controller("MenuSettingController", function($scope, $http) {
initTree();
});
Subpage
<script type="text/javascript">
function initTree(){
console.log("in");
}
</script>
Thanks a lot.
If you want to call a function which are defined in subpage, you can wrap it into the current window object. Moreover, you can also wrap object into your window object.
Then, you can call your function, into your controllers for example.
Wrap function
Controller
(function(){
function Controller($scope) {
initTree();
}
angular
.module('app', [])
.controller('ctrl', Controller);
})();
Subpage
<script type="text/javascript">
(function(){
function init(){
console.log('init');
}
//Wrap our init function into our window object
window.initTree = init;
})();
</script>
Wrap object
But, as i said, you can wrap object to the window object, so you can do :
Controller
(function(){
function Controller($scope) {
//Call our init function
app_function.init();
//Call our setter
app_function.set(42);
}
angular
.module('app', [])
.controller('ctrl', Controller);
})();
Subpage
<script type="text/javascript">
//initialize our anonymous function with the app_function or an empty object
(function(app){
function init(){
console.log('init');
}
function set(n){
console.log('Set value : ' + n);
}
//Register our function
app.init = init;
app.set = set;
})(window.app_function = window.app_function || {});
</script>
Use angular services
Use angular services is a good practice, it will make your code more reusable and clean.
You have to know that all angular services are singletons. So, you can easily share common logic, data between controller.
Controller
(function(){
function Controller($scope, Service) {
//Call our init function
Service.init();
//Call our setter
Service.set(42);
}
angular
.module('app', [])
.controller('ctrl', Controller);
})();
(function(){
function Controller2($scope, Service) {
var old = Service.get();
//Retrieve 42
console.log(old);
//Call our init function
Service.init();
//Call our setter with new value
Service.set(++old);
var newValue = Service.get();
//Retrieve 43
console.log(newValue);
}
angular
.module('app')
.controller('ctrl2', Controller2);
})();
Service
(function(){
function Service() {
var data;
function init(){
console.log('init');
}
function get(){
return data;
}
function set(n){
data = n;
console.log('Set value : ' + n);
}
//Create our object with several method
var factory = {
set: set,
init: init,
get: get
};
return factory;
}
angular
.module('app')
.factory('Service', Service);
})();
I'm trying to communicate between two controllers. I'm aware that this can be done by raising an event and then using $rootScope.$broadcast, but is not advisable for large-scale applications. I have seen a lot of blog posts which recommend using a service to communicate, but have not be able to succeed to implement. My actual code is more complicated, but here is the gist:
HTML:
<body ng-app="app">
<div ng-controller="MainCtrl">
<span>Source: {{count}}</span>
<button ng-click="updateCount()">Increase Count</button>
</div>
<div ng-controller="ListCtrl">
Destination: {{updatedCount}}
</div>
</body>
JS:
(function () {
var app = angular.module("app", []);
app.factory("ShareDataSvc", function ($log) {
var currentCount = 0;
var set = function (val) {
$log.info('Setting service value to: ' + currentCount);
currentCount = val;
}
var get = function () {
return currentCount;
}
return {
set: set,
get: get
}
});
app.controller("MainCtrl", ['$scope', 'ShareDataSvc', function ($scope, ShareDataSvc) {
$scope.count = ShareDataSvc.get();
$scope.updateCount = function () {
$scope.count = $scope.count + 1;
ShareDataSvc.set($scope.count);
}
}]);
app.controller("ListCtrl", ["$scope", "ShareDataSvc", function ($scope, ShareDataSvc) {
$scope.updatedCount = ShareDataSvc.get();
// trigger alert if count updated
$scope.triggerAlert = function () {
alert('Count updated!');
}
}]);
}());
I'm trying to understand why the count in the destination is not updated by Angular even though it is data-bound. It is my understanding that when the count is updated in the SharedDataSvc, the updatedCount property will be recalculated.
What am I doing wrong here? The end result is to trigger the alert on every count update.
You run into the old copy by value problem. When you do
$scope.updatedCount = ShareDataSvc.get();
The updated count property is being set to the value that is returned from your get function, and therefore doesn't see future changes to the value being tracked in your service. You have two options to get around this. One is to add a watch to each of your controllers to monitor the value in the service. Not ideal. The second is to have object property in your service track the value and data bind that object to your scope. Something like (note I only show the interesting parts):
app.factory("ShareDataSvc", function ($log) {
var set = function (val) {
$log.info('Setting service value to: ' + currentCount);
this.data.count = val;
}
return {
data: {count: 0}
set: set
}
});
app.controller("MainCtrl", ['$scope', 'ShareDataSvc', function ($scope, ShareDataSvc) {
$scope.data = ShareDataSvc.data;
$scope.updateCount = function () {
ShareDataSve.data.count++; // and increment function in the service would be better
}
}]);
app.controller("ListCtrl", ["$scope", "ShareDataSvc", function ($scope, ShareDataSvc) {
$scope.data = ShareDataSvc.data;
}]);
Then in your HTML
<body ng-app="app">
<div ng-controller="MainCtrl">
<span>Source: {{data.count}}</span>
<button ng-click="updateCount()">Increase Count</button>
</div>
<div ng-controller="ListCtrl">
Destination: {{data.count}}
</div>
</body>
I'm trying to inject the factory Application into the ApplicationService factory. Both are defined in the same module.
Application factory (application.model.js)
(function(Object, coreModule) {
'use strict';
// the factory to expose that allows the creation of application instances
var ApplicationFactory = function() {
console.log("Application factory!");
return {foo: 'bar'};
}
coreModule.factory('Application', [ApplicationFactory]);
})(Object, angular.module('core'));
ApplicationService factory (application.service.js)
(function(coreModule) {
'use strict';
var ApplicationService = function(Application) {
var api = {
shout = function() {console.log(Application);}
};
return api;
}
ApplicationService.$inject = ['Application'];
coreModule.factory('ApplicationService', [ApplicationService]);
})(angular.module('core'));
Then I'm injecting ApplicationService factory into a controller and calling the method shout. I get undefined when in the console's log, Application is always undefined. If in a controller I innject Application it works. So i know both factories are working standalone.
Both files are being imported in my index.html.
I've spent hours looking for the issue but I can't find it. What am I doing wrong?
Please see working demo below.
You've got 2 options.
a) Remove square brackets here:
coreModule.factory('ApplicationService', ApplicationService)
b) Add injected Application as first element before ApplicationService:
coreModule.factory('ApplicationService', ['Application', ApplicationService])
var app = angular.module('core', []);
app.controller('firstCtrl', function($scope, ApplicationService) {
ApplicationService.shout();
});
(function(Object, coreModule) {
'use strict';
// the factory to expose that allows the creation of application instances
var ApplicationFactory = function() {
console.log("Application factory!");
return {
foo: 'bar'
};
};
coreModule.factory('Application', [ApplicationFactory]);
})(Object, angular.module('core'));
(function(coreModule) {
'use strict';
var ApplicationService = function(Application) {
var api = {
shout: function() {
console.log(Application);
}
};
return api;
};
ApplicationService.$inject = ['Application'];
coreModule.factory('ApplicationService', ApplicationService);
})(angular.module('core'));
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="core">
<div ng-controller="firstCtrl">
</div>
</body>