angularjs - use injected service to get properties - angularjs

I'm writing a basic calculator app on jsfiddle to get some more experience with angular and I wanted to know if injected services can be used like objects to get properties. For example:
angular.module('CalcApp', [])
.controller('CalcVm', CalcVm)
.service('MathOperations', MathOperations);
angular.$inject = ['MathOperations'];
function CalcVm(MathOperations) {
var vm = this;
vm.xyz = '';
//code
}
function MathOperations() {
var addOp = '+';
var subtractOp = '-';
//etc..
}
is it possible to do this in the view:
<div ng-controller='CalcVm as calcVm'>
<button>{{calcVm.MathOperations.addOp}}</button>
</div>
should I bind the service to a variable in the controller?
function CalcVm(MathOperations) {
var vm = this;
vm.xyz = '';
vm.MathOperations = MathOperations;
//code
}

Ok so I've been experimenting with this and I've figured it out.
what worked was the following:
angular.module('CalcApp', [])
.controller('CalcVm', CalcVm)
.service('MathOperations', MathOperations);
angular.$inject = ['MathOperations'];
function CalcVm(MathOperations) {
var vm = this;
vm.MathOperations = MathOperations;
//more code
}
function MathOperations() {
this.addOp = '+';
this.subtractOp = '-';
//etc..
}
notice that I've used the keyword this in the service and I've assigned the injected service to a variable in my controller.
I'm not sure if this is good or bad practice and if anyone knows please edit this answer below the line with further info.

Related

How to use Angular controller in Zeppelin

I'm new to Zeppelin, recently I'm study how to use Zeppelin in my current project. I want to add a Angular controller in Zeppelin paragraph. But it's failed. Can you please give me some hints how to solve it? Below is my code.
println(s"""
%angular
<script>
angular.module('zeppelinWebApp').controller('myNewController', myNewController);
function myNewController() {
var vm = this;
vm.publicVariable = {};
// Controller's public functions
vm.myControllerPublicFunction = myControllerPublicFunction;
_init();
function myControllerPublicFunction() {
publicVariable = publicVariable + 1;
}
function _init() {
vm.myControllerPublicFunction();
}
}
</script>
<div ng-controller="myNewController as newCtrl">
<div ng-click="newCtrl.myControllerPublicFunction" ng-bind='newCtrl.publicVariable'></div>
</div>
""")
Been struggling with this myself. The best answer I've come up with is to create a pseudo-controller by grabbing a scoped element using jQuery (based off this GitHub gist):
println(s"""
%angular
<script>
var element = $('#ctrlHook');
var scope = angular.element(element.parent('.ng-scope')).scope().compiledScope;
(function myNewController() {
var vm = scope;
vm.publicVariable = 0;
// Controller's public functions
vm.myControllerPublicFunction = myControllerPublicFunction;
_init();
function myControllerPublicFunction() {
vm.publicVariable = vm.publicVariable + 1;
}
function _init() {
vm.myControllerPublicFunction();
}
})();
</script>
<div id="ctrlHook">
<div ng-click="myControllerPublicFunction" ng-bind='publicVariable'></div>
</div>
""")
You can of course remove the function block and just operate on scope directly instead of on vm, but I left it in to adhere to your original example as much as possible (I tidied up some variable references where you were calling publicVariable instead of vm.publicVariable and treating it like a number instead of the object it was initialised as).
NB: I cannot confirm whether the variable changes themselves would fix your original code, but I have tested grabbing the scope using the method above and it seems to work. Hope it helps you out.

AngularJs - service does not update controller

I am trying to implement this simple Plunker with no success.
I have a simple service (factory) :
(function () {
'use strict';
angular
.module('app.core')
.factory('PropertiesService', PropertiesService);
function PropertiesService() {
var sefl = this;
self.name = 'Properties Service'
self.properties = {};
self.setProperties = function (prop)
{
self.properties = prop;
}
return self;
}
})();
I am calling this service from a directive :
var prop = { 'top': top, 'left': left, 'position': position };
service.setProperties(prop);
The contoller being updated is :
(function () {
'use strict';
angular
.module('app.properties')
.controller('Properties', Properties);
Properties.$inject = ['PropertiesService'];
function Properties(PropertiesService) {
var vm = this;
vm.collection = {};
setCollection();
function setCollection() {
for (var key in PropertiesService.properties) {
if (PropertiesService.properties.hasOwnProperty(key)) {
vm.collection[key] = PropertiesService.properties[key];
}
}
};
}
})();
Lastly , I am showing the data in html like this :
<div ng-controller="Properties as vm">
<ul class="list-group">
<li class="list-group-item" ng-repeat="(key, value) in vm.collection">
<span>{{key}}</span> : <span>{{value}}</span>
</li>
</ul>
</div>
I understand why i'm getting result only on initialization but I can not find the way to solve it,to make the controller updated when the service is changed (and it does) .
Thanks
Just to note something.
In your plunker you use a service and you try the same code with a factory. This cannot work. there are some differences between the two providers.
Either you use a factory:
function PropertiesFactory() {
// facory doens't get invoked with the new keyword
// so there is no this
var self = {};
self.name = 'Properties Factory'
self.properties = {};
self.setProperties = function (prop)
{
self.properties = prop;
}
return self;
}
or a service:
function PropertiesService() {
var sefl = this;
self.name = 'Properties Service'
self.properties = {};
self.setProperties = function (prop)
{
self.properties = prop;
}
// there is no need for return
// since th service gets invoked with the new keyword
}
form the angularjs docs about providers:
The Service recipe produces a service just like the Value or Factory
recipes, but it does so by invoking a constructor with the new
operator. The constructor can take zero or more arguments, which
represent dependencies needed by the instance of this type.
As it turn out i was hiding an important part of the code , not deliberately but from lack of understanding.
My directive is listening on DOM events and acting upon their changed data.
After reading this article (and help from my CTO...) I understood i needed to manually call $scope.$apply().
Now I have an element i can resize,drag etc. and have its changed properties eflect on the screen.
Now the binding is working again I can revert the controller code to look like this:
function Properties(PropertiesService) {
var vm = this;
vm.collection = PropertiesService.data;
}
Everything is in sync.
Sorry for the partial data , and thanks for the help.
Gilad

LocalStorage inside a service doesn't work

I have a code that works perfectly inside a controller but after moving it to service, it seems to not work and crush right after this:
return JSON.parse(window.localStorage.getItem("SavedContacts"));
the service code:
var app = angular.module('myApp', ["ngStorage"]);
app.service('ContactManager', function()
{
this.Contacts={};
this.GetJsonFile = function ()
{
return JSON.parse(window.localStorage.getItem("SavedContacts"));
}
this.Contacts = this.GetJsonFile();
...
}
Thanks for any help.
EDIT:
A sample : http://plnkr.co/edit/jjInJp4lJcC1oCvXZ1oN?p=preview

AngularJS - using setters and getters within a Service to store variables. Is it possible?

If I ran the code below would a variable called language that exists within a service be able to be set and taken from various controllers?
app.service('serviceName', function() {
var language;
this.getLanguage = function()
{
return language;
}
this.setLanguage = function(lan)
{
language = lan;
}
});
Controller 1:
serviceName.setLanguage('english');
Controller 2:
$scope.lan = serviceName.getLanguage();
Also if this is undesirable what would be a better way to keep variables in a service that can be accessed throughout different controllers?
You can also combine everything in a single method:
app.service('serviceName', function () {
var _language;
this.language = function(value){
if(value){
_language = value;
} else {
return _language;
}
};
});
Your case is pretty simple, so you can even just expose the variable directly:
app.service('serviceName', function () {
this.language = null;
});

Angular Access scope data to factory?

I have a situation where i am getting data on scroll from a service. Now i need to filter data using popular data and latest post
Here is my service:
App.factory('Serviec', function ($http, $rootScope) {
var Hututoo = function () {
this.items = [];
this.busy = false;
this.after = 'Serviec_0';
};
Serviec.prototype.nextPage = function () {
if (this.busy) return;
this.busy = true;
// return undefined
console.log($rootScope.listtype);
$http.get(baseurl + 'ajax/gethome?after=' + this.after).success(function (data) {
var items = data;
for (var i = 0; i < 5; i++) {
this.items.push(items[i]);
// debugger;
}
this.after = "Hututoo_" + this.items.length;
this.busy = false;
}.bind(this));
};
return Serviec;
});
In controller:
$scope.data= new Serviec();
$scope.listtype= 'latest';
$scope.changelist = function(str){
$rootScope.listtype = str;
$scope.data.items=[];
$scope.data.after = 'Serviec_0';
$http.post(baseurl+"ajax/gethome","after="+$scope.hututoo.after+"&list="+str).success(function(data){
$scope.data.items = data;
});
}
Html
<li ng-click="expression = 'latest';changelist('latest');" ng-class="{latest_icon:expression == 'latest'}">Latest Hoot</li>
<li ng-click="expression = 'popular';changelist('popular');" ng-class="{popular_icon:expression == 'popular'}">Popular Hoots</li>
So with these click i need to order data .I have to make http call to get data according to user click.
I was thinking that i can make a scope data that define listing type and get it in factory.
How can i inject this scope in Serviec Factory. I have tried it using rootscope. initally list type is set to latest , but it shows undefined. So what would be the best method achieve this?
Update:
Now i can access scope data in angular service, but small issue comes here is on list click previous item's in scope doesn't get empty and new items get pushed into the scope.
So demand is on list click previous data become zero and new get pushed into the scope.
Pass the $rootScope to controller and set the listtype as required.
App.controller('MainCtrl', function($scope, $rootScope, Hututoo) {
$scope.hututoo = new Hututoo();
$scope.listtype= 'latest';
$scope.changelist = function(str){
$rootScope.listtype= str;
$scope.hututoo = new Hututoo();
$scope.hututoo.nextPage();
}
});
Plunker
Avoid using $rootScope -- it's bad practice, much like using the head object in pure JS. You're already able to share data between the factory and controller, so why not just make listtype a property of the factory:
var Hututoo = function () {
...
this.listtype = 'latest';
};
and use it in your controller as you are other properties:
$scope.changelist = function(str){
$scope.hututoo.listtype = str;
...
};
Demo <-- ajax requests don't work for obvious reasons
$scope is not available to inject in services however you can pass it using parameters like so.
app.factory('Hututoo', function ($resource) {
var somePrivateVar = [];
return {
set: function(scopeVar){
somePrivateVar.push(scopeVar);
},
get: function(){
return somePrivateVar;
}
}
});
then in controller
Hututoo.set($scope.anyVar);

Resources