AngularJS: Modifying Service within Service doesn't update Controller - angularjs

I have my model in a Service, all my model is in an object, I would like to be able to reset my model by just reassign my model to an empty object, but it doesn't seem to work, but if I delete a property directly it does.
How could I reset my model without having to delete every property, refresh the page or doing big changes?
(function () {
var myApp = angular.module('myApp', []);
myApp.controller('MyController', function (MyService) {
var _this = this;
_this.model = MyService.model;
_this.myService = MyService;
_this.deleteInService = function () {
MyService.functions.resetModel();
};
});
myApp.service('MyService', function () {
var obj = {};
obj.model = {x: 1};
obj.functions = {};
obj.functions.resetModel = function () {
//delete obj.model.x; //THIS WORKS!
obj.model = {x: 1}; //BUT THIS DOESN'T :(
};
return obj;
});
})();
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
<script src="changingModelInService.js"></script>
</head>
<body ng-app="myApp" ng-controller="MyController as myCtrl">
{{myCtrl.model.x}}<div><input ng-model="myCtrl.model.x"/></div>
<button ng-click="myCtrl.deleteInService()">Delete X in service</button>
</body>
</html>
Thank you.
Edit: doing _this.model = MyService.model it's not possible because I share my Service with many controllers

I think one solution to your problem would be to create a default model variable like a master copy and use angular.copy with two parameters resetting the model to a master version when invoking that method.
See the angular.copy documentation here. You'll notice the live demo actually shows a reset functionality.
I've updated the live demo plunker to show the behaviour I think you desire http://plnkr.co/edit/BJ....
Hope that helps!
UPDATE::
A possible implementation although will require testing would be as follows;
myApp.service('MyService', function () {
var masterModel = {x: 1};
var obj = {
model: {x: 1},
functions: {
resetModel: function() {
angular.copy(masterModel, obj.model);
}
}
};
return obj;
});

Other than angular.copy, another solution is just to not use _this.model and use _this.myService.model instead or to change your deleteInService function to
_this.deleteInService = function () {
MyService.functions.resetModel();
_this.model = MyService.model;
};
The reason you're getting this problem is because you're doing something like this:
service.model = foo;
controller.model = service.model; // implies controller.model = foo;
service.reset(); // => service.model = bar;
// But notice that controller.model still points to the old object foo
Run the code snippet below to see what I mean.
(function () {
var myApp = angular.module('myApp', []);
myApp.controller('MyController', function (MyService) {
var _this = this;
_this.model = MyService.model;
_this.serviceModel = MyService.model;
_this.myService = MyService;
_this.deleteInService = function () {
MyService.functions.resetModel();
_this.serviceModel = MyService.model;
};
});
myApp.service('MyService', function () {
var obj = {};
obj.model = {x: 1};
obj.functions = {};
obj.functions.resetModel = function () {
//delete obj.model.x; //THIS WORKS!
obj.model = {x: 1}; //BUT THIS DOESN'T :(
};
return obj;
});
})();
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
<script src="changingModelInService.js"></script>
</head>
<body ng-app="myApp" ng-controller="MyController as myCtrl">
<pre>myCtrl.model = {{myCtrl.model}}</pre>
<pre>myCtrl.serviceModel = {{myCtrl.serviceModel }}</pre>
<pre>myCtrl.myService.model = {{myCtrl.myService.model}}</pre>
<div><input ng-model="myCtrl.model.x"/></div>
<button ng-click="myCtrl.deleteInService()">Delete X in service</button>
</body>
</html>

Related

$http get shortcut messing up program in AngularJS?

In the script below, I have posted a boiled down version of my code. It's essentially a simplified search engine.
The script loops through the $scope.list_of_fruit array, and filters it according to what is typed on a simple html input text box.
<script>
var app = angular.module("myapp",[]);
app.controller("usercontroller", function($scope){
$http
.get("test.php")
.then(function (response) {
$scope.myData = response.data.records;
});
$scope.list_of_fruit = ["apple", "banana", "pear", "kiwi"];
$scope.complete = function(boxtext){
var output = [];
angular.forEach($scope.list_of_fruit, function(fruit){
if(fruit.toLowerCase().indexOf(boxtext.toLowerCase()) == 0)
{
output.push(fruit);
}
});
$scope.filteredfruit = output;
}
});
</script>
This works fine and dandy, but when I paste that http get request up top, that is completely unrelated to that $scope.complete loop, the $scope.complete loop just stops working.
Am I missing something obvious?
app.controller("usercontroller", function($scope){
You don't have $http defined, so you are probably getting an javascript error.
Add $http to the function parameters:
app.controller("usercontroller", function($scope, $http){
I created a snippet and this appears to work now
var app = angular.module('myApp', []);
app.controller("usercontroller", function($scope, $http){
$http
.get("https://jsonplaceholder.typicode.com/posts")
.then(function (response) {
$scope.myData = response.data.records;
});
$scope.list_of_fruit = ["apple", "banana", "pear", "kiwi"];
$scope.complete = function(boxtext){
console.log(boxtext);
var output = [];
angular.forEach($scope.list_of_fruit, function(fruit){
if(fruit.toLowerCase().indexOf(boxtext.toLowerCase()) == 0)
{
output.push(fruit);
}
});
$scope.filteredfruit = output;
}
});
<!DOCTYPE html>
<html ng-app='myApp'>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://rawgit.com/angular/bower-angular/master/angular.min.js"></script>
<div ng-controller="usercontroller as vm">
{{list_of_fruit}}
{{filteredfruit}}
<input type="text" ng-model="search"/>
<button ng-click="complete(search)">Do something</button>
</div>
</body>
</html>

Split a string in angularjs controller

I am trying to split a single string into array or JSON format. Kindly help in doing that in angular js controller (not in HTML view).
The string format is like,
string="Name1;Email1;ID1~Name2;Email2;ID2"
None of the ways I tried worked. I tried using string.split('~') but I am getting an error as split is not a function.
myView.service('ViewService', [function () {
var temp = [];
var fstring = [];
this.SplitUser = function (userstring) {
debugger;
//temp = userstring.split('~');
angular.forEach(userstring, function (value, key) {
fstring.push({
'Name': temp.split(';')[i],
'EmailID': temp.split(';')[i++],
'ID': temp.split(';')[i++]
});
})
console.log(temp);
console.log(fstring);
return temp;
}
Need to loop the temp array.not userstring.Also when you are pushing to the fstring array remove the i and use the position as a number
fstring.push({
'Name': value.split(';')[0],
'EmailID': value.split(';')[1],
'ID': value.split(';')[2]
);
change your service like this.
.service('ViewService', [function () {
var temp = [];
var fstring = [];
this.SplitUser = function (userstring) {
debugger;
temp = userstring.split('~');
angular.forEach(temp, function (value, key) {
fstring.push({
'Name': value.split(';')[0],
'EmailID': value.split(';')[1],
'ID': value.split(';')[2]
});
})
console.log(temp);
console.log(fstring);
return temp;
}
}])
Demo
angular.module("app",[])
.controller("ctrl",function($scope,ViewService){
var string="Name1;Email1;ID1~Name2;Email2;ID2";
ViewService.SplitUser(string)
}).service('ViewService', [function () {
var temp = [];
var fstring = [];
this.SplitUser = function (userstring) {
debugger;
temp = userstring.split('~');
angular.forEach(temp, function (value, key) {
fstring.push({
'Name': value.split(';')[0],
'EmailID': value.split(';')[1],
'ID': value.split(';')[2]
});
})
console.log(temp);
console.log(fstring);
return temp;
}
}])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
</div>
var string = "Name1;Email1;ID1~Name2;Email2;ID2";
// Initial split in entries
var splitStrings = string.split('~');
var objects = [];
for(var i = 0; i < splitStrings.length; i++) {
// split into properties
var objProps = splitStrings[i].split(';');
var myObj = {};
myObj.name = objProps[0];
myObj.mail = objProps[1];
myObj.id = objProps[2];
objects.push(myObj);
}
console.log(objects);
This should split your string and put it into objects. Then add those objects into an array.
If you want to use JSON and have control over the code that sends you the message I would suggest you use JSON.parse() and JSON.stringify() instead.
This sollution expect a strict structure like the one you posted and has no eror handling.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = [];
var string="Name1;Email1;ID1~Name2;Email2;ID2"
var arr = string.split('~');
angular.forEach(arr, function (value, key) {
$scope.name.push({
'Name': value.split(';')[0],
'EmailID': value.split(';')[1],
'ID': value.split(';')[2]
});
})
console.log($scope.name);
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.12/angular.js" data-semver="1.4.9"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
</body>
</html>

Angular Storing array into Cookie

I have a function below that works fine and passes info into and retrieves from a cookieStore without issue
$scope.num = 0
$scope.nums = []
$scope.increment = function () {
$scope.num++
}
$scope.$watch('num', function () {
$scope.nums.push($scope.num)
})
$scope.storeProductsInCookie=function(){
$cookieStore.put("invoices",$scope.nums)
};
$scope.getProductsInCookie=function(){
console.log( $cookieStore.get("invoices",$scope.nums));
}
However when I try with the below verufyGuess function that is injecting the Index and no as parameters into the function it fails to place into the cookieStore
$scope.verifyGuess = function (Index , no) {
$scope.votes = {};
$scope.newVotes = []
$scope.votes[Index] = $scope.votes[Index] || 0;
$scope.votes[Index]+= no;
$scope.$watch('votes', function () {
$scope.newVotes.push($scope.votes)
})
$scope.storeProductsInCookie=function(){
$cookieStore.put("invoices",$scope.newVotes)
};
$scope.getProductsInCookie=function(){
console.log( $cookieStore.get("invoices",$scope.newVotes));
}
$cookieStore is Deprecated: (since v1.4.0)
Please use the $cookies service instead.
$scope.nums is an array of strings.So $cookieStore is storing them as string(cookies only support strings to store).
In second case $scope.newVotes is an array of objects. cookies wont store objects.
you must use $cookieStore.put("invoices", JSON.stringify($scope.newVotes))
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.12/angular.js" data-semver="1.4.9"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.12/angular-cookies.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<script>
var app = angular.module('plunker', ['ngCookies']);
app.controller('MainCtrl', function($scope, $cookies) {
$scope.votes = {};
$scope.newVotes = []
var Index = 0;
$scope.votes[Index] = $scope.votes[Index] || 0;
$scope.votes[Index] += 10;
$scope.newVotes.push($scope.votes)
$scope.storeProductsInCookie = function() {
$cookies.put("invoices", JSON.stringify($scope.newVotes))
};
$scope.getProductsInCookie = function() {
console.log($cookies.get("invoices"));
}
$scope.storeProductsInCookie();
$scope.getProductsInCookie();
});
</script>
</body>
</html>

Pulled out all my hair on an Angular unpr error

So I am getting an angular [$injector:unpr] error. Yes, I know what that normally means...I haven't defined something somewhere, or I am redefining the module over and over, or the like...but for the life of me I'm struggling to see the issue in my code.
I'm sure I'm missing something insanely basic, but after I've stared at code for a couple of hours, I go blind to it.
My HTML File:
<!DOCTYPE html>
<html ng-app="email">
<head>
<meta charset="UTF-8">
<title>Authentication</title>
<link href='https://fonts.googleapis.com/css?family=Roboto:400,100,300,500,700' rel='stylesheet' type='text/css'/>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
</head>
<body>
<script src="bower_components/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="node_modules/angular/angular.min.js"></script>
<div ng-controller="EmailAuthController as auth">
<h1>Authentication</h1>
<p>Request: [{{auth.request}}]</p>
<p>{{auth.response}}</p>
<p>{{1+2}}</p>
</div>
<script type="text/javascript" src="js/controllers/email.js"></script>
</body>
</html>
My email.js file (As you can see, I've commented out some stuff to try to isolate the issue):
/* global angular parseGet */
function parseGet(val) {
var result = '', // = "Not found",
tmp = [];
var items = location.search.substr(1).split('&');
for (var index = 0; index < items.length; index++) {
tmp = items[index].split('=');
if (tmp[0] === val) {
result = decodeURIComponent(tmp[1]);
}
}
return result;
}
(function () {
angular
.module('email', [])
.controller('EmailAuthController', [ '$scope','authFactory', function ($scope,authFactory) {
var vm = this,
req = parseGet('hash') || '';
vm.request = req;
// authFactory.validate(req)
// .then(function (response) {
// vm.response = response.data;
// });
}])
.factory('authFactory', [ '$rootScope', '$http', 'config', function ($rootScope, $http, config) {
var validate = function (hash) {
var url = config.SERVICE_URI + '/auth/email/' + hash;
return $http.get(url);
};
return {
validate: validate
};
}]);
})();
From the code you've given it appears config is not defined in your authFactory injection.
.factory('authFactory', [ '$rootScope', '$http', 'config', function(a, b, c) {} ]); // config is not defined

Syntax to access rootScope variable in MyController

In the below code,
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.20/angular.js"></script>
<script type="text/javascript">
function MyController() {
this.Name = "jag";
this.sal = "4500";
}
MyController.prototype.getAnnualSal = function(){
return (this.sal) * 12;
}
var app = angular.module("sample", []).run(function($rootScope) {
$rootScope.variable = 1;
});
app.controller("emp", MyController);
</script>
</head>
<body ng-app="sample">
<div ng-controller="emp as o" >
Hello {{o.Name}}, your annual salary is {{o.getAnnualSal()}}
</div>
</body>
</html>
Using run syntax, $rootScope.variable is introduced at module(sample) level.
What is the syntax to access $rootScope.variable in MyController?
Inject rootScope in controller like this.
angular.module('sample', []).controller('emp', function($scope, $rootScope) {
};
Aside from your issue I dont know why you are mixing controller code in view.Angular is built on MVVM pattern.So separation of controller and view is recommended.
You could do the following, inject $rootScope into the controller
<script type="text/javascript">
function MyController($rootScope) {
this.Name = "jag";
this.sal = "4500";
}
MyController.prototype.getAnnualSal = function(){
return (this.sal) * 12;
}
var app = angular.module("sample", []).run(function($rootScope) {
$rootScope.variable = 1;
});
MyController.$inject = ['$rootScope'];
app.controller("emp", MyController);
</script>

Resources