Angular - Service to calculate sum of 2 scopes - javascript

Learning how to use services but really having a hard time. Trying to make a simple calculator to provide the sum of 2 scope value (2 inputs). My functions seems to be taking the values and sending them okay. But my result scope dosent seem to be changing or updating at all when I fire my functions.
Here what I got so far:
Jsfiddle:
https://jsfiddle.net/9bz4Lwxa/528/
HTML:
<body ng-app="myApp" ng-controller="myController">
Val1: <input ng-model="val1"> {{val1}} <br>
Val2: <input ng-model="val2"> {{val2}} <br><br>
Total result: <input ng-model="result"> {{result}} <br>
<input type="button" ng-click="calculate_controller()" value="Calculate"><br>
</body>
SCRIPT:
angular.module('myApp', [])
.controller('myController', function($scope, businessRepository) {
$scope.result = businessRepository.result_service();
$scope.val1 = "";
$scope.val2 = "";
$scope.calculate_controller = function() {
console.log("Hello");
businessRepository.calculate_service($scope.val1, $scope.val2)
};
})
.factory('businessRepository', function($http) {
return {
result_service: function(data){
console.log("test function launched", data)
return data;
},
calculate_service: function(val1, val2){
var result = val1 + val2;
this.result_service(result);
}
};
});

You need to return data from the service businessRepository and need to consume it in the controller myController. Also you need to convert val1 and val2 to Number. Here in snippet I have used + to achieve it.
angular.module('myApp', [])
.controller('myController', function ($scope, businessRepository) {
$scope.calculate_controller = function () {
$scope.result = businessRepository.calculate_service(+$scope.val1, +$scope.val2)
};
})
.factory('businessRepository', function ($http) {
return {
result_service: function (data) {
return data || 0;
},
calculate_service: function (val1, val2) {
var result = val1 + val2;
//Return the data from
return this.result_service(result);
}
};
});
angular.module('myApp', [])
.controller('myController', function($scope, businessRepository) {
$scope.calculate_controller = function() {
$scope.result = businessRepository.calculate_service(+$scope.val1, +$scope.val2)
};
})
.factory('businessRepository', function($http) {
return {
result_service: function(data) {
return data;
},
calculate_service: function(val1, val2) {
var result = val1 + val2;
return this.result_service(result);
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
Val1:
<input ng-model="val1">
<br>Val2:
<input ng-model="val2">
<br>
<br>Total result:
<input ng-model="result">{{result}}
<br>
<input type="button" ng-click="calculate_controller()" value="Calculate">
<br>
</div>

You need to change the calculate_service by :
calculate_service: function (val1, val2) {
var result = parseInt(val1) + parseInt(val2);
return this.result_service(result);
}
And calculate_controller by :
$scope.calculate_controller = function () {
$scope.result = businessRepository.calculate_service($scope.val1, $scope.val2)
};

Related

Angular service function isn't working on user input

I'm trying to learn how to make angular services, so I' ve made one but it only works as the page loads and it gives input value instead of function result.
HTML:
<input type="text" ng-model="hexVal">
<p>Hex service: {{hex(hexVal)}}</p>
JS:
Service itself:
app.service('hexafy', function() {
this.myFunc = function (x) {
return x.toString(16);
};
});
Usage of service:
$scope.hexVal = 255;
$scope.hex = function(arg){
return hexafy.myFunc(arg);
};
The input text needs to be parsed into a number:
app.service('hexafy', function() {
this.myFunc = function (x) {
return parseInt(x).toString(16);
};
});
The DEMO
angular.module("app",[])
.service('hexafy', function() {
this.myFunc = function (x) {
return parseInt(x).toString(16);
};
})
.controller('ctrl', function($scope,hexafy) {
$scope.hexVal = 255;
$scope.hex = function(arg){
return hexafy.myFunc(arg);
};
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="ctrl">
<input type="text" ng-model="hexVal">
<p>Hex service: {{hex(hexVal)}}</p>
</body>

use $http.get in a service/factory to return a collection

I try to use a http.get promise in an angularjs service, do some manipulation on the obtained collection and finally return it to a controller...
My question is how to use a $http.get() in a service in order to obtain and manipulate the result before returning it to the controller, like in the code bellow :
The PEN code
var app = angular.module('myApp', []);
app.controller('customersCtrl', ['$scope','customer',function($scope, customer) {
$scope.odds = customer.odds;
}]);
app.factory('customer', ['$http', function($http) {
var all = [{'Id':88, 'Name':"A"}, {'Id':89, 'Name':"ShoutNotBeHere"}];
var odds = [];
$http.get("http://www.w3schools.com/angular/customers.php")
.then(function(response) {
all = response.records;
});
angular.forEach(all, function(c, i) {
if (i % 2 == 1) {
odds.push(c);
}
});
return {odds: odds};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="customersCtrl">
Odd ids from www.w3schools.com/angular/customers.php
<ul>
<li ng-repeat="c in odds">
{{ c.Id + ', ' + c.Name }}
</li>
</ul>
</div>
</body>
Basically you could modified the data inside the ajax success call & then return that data from the success. But for returning data from ajax success you need to use promise pattern to return out data from $http.get. you need to return the object from the $http.get promise, & inside .then function of $http.get you could manipulate data.
Factory
app.factory('customer', ['$http', function($http) {
var all, odds = [];
var getData = function() {
return $http.get("http://www.w3schools.com/angular/customers.php")
.then(function(response) {
all = response.records;
angular.forEach(all, function(c, i) {
if (i % 2 == 1) {
odds.push(c);
}
});
return odds
});
}
return {
getData: getData
};
}]);
Controller
app.controller('customersCtrl', ['$scope','customer',function($scope, customer) {
customer.getData().then(function(response){
$scope.odds = response;
});
}]);
I took the liberty to modify your code to return a promise from the factory, so you can set the value as soon as the promise is resolved.
var app = angular.module('myApp', []);
app.controller('customersCtrl', ['$scope','customer',function($scope, customer) {
customer.then(function(data){
$scope.odds = data.odds;
customer.then(function(data){
console.log(data);
});
});
}]);
app.factory('customer', ['$http', function($http) {
var all = [{'Id':88, 'Name':"A"}, {'Id':89, 'Name':"ShoutNotBeHere"}];
var odds = [];
return $http.get("http://www.w3schools.com/angular/customers.php")
.then(function(response) {
all = response.data.records;
angular.forEach(all, function(c, i) {
if (i % 2 == 1) {
c.Id = i;
odds.push(c);
}
});
return {odds: odds};
});
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="customersCtrl">
Odd ids from www.w3schools.com/angular/customers.php
<ul>
<li ng-repeat="c in odds">
{{ c.Id + ', ' + c.Name }}
</li>
</ul>
</div>
</body>

Angular service with different angular app

Here i am using angular service.In my case i am getting value for first app but not for second .please help me .
thank you.
here is my html:-
<div ng-app="mainApp" ng-controller="CalcController">
<p>Enter a number: <input type="number" ng-model="number" />
<button ng-click="multiply()">X<sup>2</sup></button>
<p>Result: {{result}}</p>
</div>
<div ng-app="myApp2" ng-controller="myController2">
<p>Enter a number: <input type="number" ng-model="numberSecond" />
<button ng-click="multiplyValue()">X<sup>2</sup></button>
<p>Result: {{result2}}</p>
</div>
here is js:-
angular.module('myReuseableMod',[]).factory('$myReuseableSrvc',function()
{
// code here
var factory = {};
factory.multiply = function(a)
{
return a * a
}
return factory;
});
var mainApp = angular.module("mainApp", ['myReuseableMod']);
mainApp.controller('CalcController',['$scope', '$myReuseableSrvc',function($scope, $myReuseableSrvc) {
alert("inside controller");
$scope.multiply = function()
{
alert("hello1");
$scope.result = $myReuseableSrvc.multiply($scope.number);
}
}]);
var mainApp2 = angular.module("myApp2", ['myReuseableMod']);
mainApp.controller('myController2',['$scope', '$myReuseableSrvc',function($scope, $myReuseableSrvc) {
alert("inside controller");
$scope.multiplyValue = function()
{
alert("hello1");
$scope.result2 = $myReuseableSrvc.multiply($scope.numberSecond);
}
}]);
Your 'myController2' is in the wrong app
mainApp.controller('myController2'
Should be:
mainApp2.controller('myController2'
EDIT:
Ah yes I see the problem. You cannot use ng-app twice like that. If you want what you are trying to achieve which is multiple applications you have to 'bootstrap' the second one:
plunk here:
http://plnkr.co/edit/qfllLO9uy6bC5OLkHnYZ?p=preview
angular.module('myReuseableMod',[]).factory('$myReuseableSrvc',function() {
var factory = {};
factory.multiply = function(a) {
return a * a
}
return factory;
});
var mainApp = angular.module("mainApp", ["myReuseableMod"]);
mainApp.controller('CalcController', ['$scope', '$myReuseableSrvc',function($scope, $myReuseableSrvc) {
$scope.multiply = function() {
$scope.result = $myReuseableSrvc.multiply($scope.number);
}
}]);
var mainApp2 = angular.module("mainApp2", []);
mainApp2.controller("MyController2", function($scope, $myReuseableSrvc) {
console.log('init B');
$scope.multiplyValue = function() {
$scope.result2 = $myReuseableSrvc.multiply($scope.numberSecond);
}
});
angular.element(document).ready(function() {
angular.bootstrap(document.getElementById("myDiv2"), ["mainApp2", "myReuseableMod"]);
});
This is a good post to read:
http://www.simplygoodcode.com/2014/04/angularjs-getting-around-ngapp-limitations-with-ngmodule/

How do I implement a cancellable editable field in Angular?

In my model, I have a field that I need several controls to bind to. One of these controls is a text box. The text box should not directly edit the field, but instead it should allow the user to type and then either commit the changes or cancel. If any other operation occurs then it should overwrite any changes in the text field. One constraint is that there are other UI components that change the value and do not have access to the local scope.
I implemented the desired behavior with a directive: http://jsfiddle.net/fLxjjmb7/3/
It works as intended, but I feel that there must be a better way to do this. Any ideas?
<div ng-app="app" ng-controller="controller">
<div>{{foo}}</div>
<button ng-click="increment()">increment</button>
<button ng-click="decrement()">decrement</button>
<br />
<div shadow="foo">
<input type="text" ng-model="foo" />
<button ng-click="commit()">update</button>
<button ng-click="cancel()">cancel</button>
</div>
</div>
var app = angular.module('app', []);
var controller = app.controller('controller', function ($scope) {
$scope.foo = 1;
$scope.increment = function () { ++$scope.foo; };
$scope.decrement = function () { --$scope.foo; };
});
var directive = app.directive('shadow', function() {
return {
scope: true,
link: function(scope, el, att) {
scope.$parent.$watch(att.shadow, function (newValue) {
scope[att.shadow] = newValue;
});
scope.commit = function() {
scope.$parent[att.shadow] = angular.copy(scope[att.shadow]);
};
scope.cancel = function() {
scope[att.shadow] = angular.copy(scope.$parent[att.shadow]);
};
}
};
});
Think you are complicating this a bit :)
View:
<div ng-controller="ShadowController">
<h1>{{foo}}</h1>
<div>
<button ng-click="increment()">increment</button>
<button ng-click="decrement()">decrement</button>
</div>
<div>
<input type="text" ng-model="tempFoo" />
<button ng-click="commit()">update</button>
<button ng-click="cancel()">cancel</button>
</div>
</div>
Controller:
.controller('ShadowController', function ($scope) {
$scope.foo = 1;
$scope.increment = function () {
++$scope.foo;
$scope.cancel();
};
$scope.decrement = function () {
--$scope.foo;
$scope.cancel();
};
$scope.commit = function () {
$scope.foo = parseFloat($scope.tempFoo);
};
$scope.cancel = function () {
$scope.tempFoo = $scope.foo;
};
$scope.cancel();
});
An even fancier way would be to keep track of changes to the temporary value and only enable commit/cancel buttons if there is a diff between original and temp.
View:
<div ng-controller="ShadowControllerAdv">
<h1>{{data.original}}</h1>
<div>
<button ng-click="increment()">increment</button>
<button ng-click="decrement()">decrement</button>
</div>
<div>
<input type="text" ng-model="data.edit" />
<button ng-click="commit()" ng-disabled="!state.hasChanged">update</button>
<button ng-click="reset()" ng-disabled="!state.hasChanged">cancel</button>
</div>
</div>
Controller:
.controller('ShadowControllerAdv', function ($scope) {
var _dataWatcher;
$scope.data = {
original: 1
};
$scope.state = {
hasChanged: false
};
function _startWatcher() {
_dataWatcher = $scope.$watch('data.edit', function (newValue, oldValue) {
if (newValue !== oldValue) {
$scope.state.hasChanged = true;
} else {
$scope.state.hasChanged = false;
}
}, true);
}
function _stopWatcher() {
if (!_dataWatcher) {
return;
}
_dataWatcher();
}
$scope.reset = function () {
_stopWatcher();
$scope.data.edit = $scope.data.original;
$scope.state.hasChanged = false;
_startWatcher();
}
$scope.commit = function () {
_stopWatcher();
$scope.data.original = parseFloat($scope.data.edit);
$scope.reset();
}
$scope.increment = function () {
$scope.data.original = $scope.data.original + 1;
$scope.reset();
};
$scope.decrement = function () {
$scope.data.original = $scope.data.original - 1;
$scope.reset();
};
$scope.reset();
});

Controller hiding $scope.var in another controller with angular

I have 2 controllers. I want to make a simple toggle where if a function is called it hides code in the other controller. Here is what I have...
Angular:
var app = angular.module('plunker', []);
app.factory('data', function () {
var fac = [];
fac.hideIt = function (hide) {
console.log(hide)
if (hide != null)
return true;
else
return false;
};
return fac;
});
app.controller('MainCtrl', function($scope, data) {
$scope.name = 'World';
console.log(data.hideIt()); //its false
$scope.hide = data.hideIt();
});
app.controller('SecCtrl', function($scope, data) {
$scope.hideAbove = function () {
var hide = true;
data.hideIt(hide);
console.log(data.hideIt(hide)) //now it is true
}
});
HTML:
<div ng-controller="MainCtrl">
<div ng-if="hide == false">
<p>Hello {{name}}!</p>
</div>
</div>
<div ng-controller="SecCtrl">
<div ng-click="hideAbove()">CLICK HERE </div>
</div>
Link to Plunkr:
http://plnkr.co/edit/zOAf5vGMTAd8A10NGiS1?p=preview
Is there no way to use a controller to hide code that is in another controller?
You dont need to use $emit, $rootScope.$broadcast or something else
in your code you asked to the factory the value of a local variable, you cant updates it because each time you start the method a new variable was created;
Here is a working example, hope it will help you
http://plnkr.co/edit/jBc3DJnzXNJUiVVwRAPw?p=preview
The factory declare some useful methods like updates and gets hide value
app.factory('HideFactory', function () {
var prototype = {};
var hide = false;
prototype.getDisplayMode = function() {
return hide;
}
prototype.hideIt = function (val) {
hide = typeof val == 'boolean' ? val : false;
return val;
};
return prototype;
});
The controllers declare some variables which are a reference to the factory methods
app.controller('MainCtrl', ['$scope', 'HideFactory',function($scope, HideFactory) {
$scope.name = 'World';
$scope.isHide = HideFactory.getDisplayMode;
}]);
app.controller('SecCtrl', ['$scope', 'HideFactory', function($scope, HideFactory) {
$scope.isHide = HideFactory.getDisplayMode;
$scope.hideAbove = function() {
HideFactory.hideIt(true);
}
}]);
And the html, the ng-if directive call the isHide method, linked to the getDisplayMode method of the factory
<body>
<div ng-controller="MainCtrl">
<div ng-if="!isHide()">
<p>Hello {{name}}!</p>
</div>
</div>
<div ng-controller="SecCtrl">
<div ng-click="hideAbove()">CLICK HERE </div>
</div>
</body>
You're about halfway there with your factory, you have most of a setter but not a getter. Here's what I'd change.
Factory:
app.factory('data', function () {
var fac = [];
var state = false;
fac.hideIt = function (hide) {
state = hide;
};
fac.hidden = function() {
return state;
}
return fac;
});
Controller:
app.controller('MainCtrl', function($scope, data) {
$scope.name = 'World';
$scope.hide = data.hidden;
});
HTML:
<div ng-controller="MainCtrl">
<div ng-hide="hide()">
<p>Hello {{name}}!</p>
</div>
</div>
Forked Plunker
please see here: http://plnkr.co/edit/3NEErc0zUpXlb1LarXar?p=preview
var app = angular.module('plunker', []);
app.factory('data', function() {
var fac = [];
var _hide = {};
hideIt = function(hide) {
console.log("from fact " + hide)
if (hide !== null) {
_hide.state = true;
return _hide;
} else
_hide.state = false;
return _hide;
};
return {
fac: fac,
hideIt: hideIt,
hide: _hide
};
});
app.controller('MainCtrl', function($scope, data) {
$scope.name = 'World';
//console.log(data.hideIt()); //its false
$scope.hide = data.hide;
});
app.controller('SecCtrl', function($scope, data) {
$scope.hideAbove = function() {
var hide = true;
data.hideIt(hide);
}
});
HTML:
<div ng-if="hide.state != true">
<p>Hello {{name}}!</p>
</div>
</div>
<div ng-controller="SecCtrl">
<div ng-click="hideAbove()">CLICK HERE</div>
</div>
</body>
You want to use $emit.
function firstCtrl($scope){
$scope.$on('someEvent', function(event, data) { console.log(data); });
}
function secondCtrl($scope){
$scope.$emit('someEvent', [1,2,3]);
}

Categories

Resources