watch rootScope variable to change the progressBar value - angularjs

app.controller("ListController1", ['$rootScope',function($rootScope) {
$rootScope.progressBar=10;
$rootScope.$watch(
function() {
return $rootScope.progressBar;
},
function(){
alert($rootScope.progressBar);
alert("changed");
},true)
}]);
app.controller("ListController2", ['$scope','$rootScope',function($scope,$rootScope) {
$scope.save=function() {
$rootScope.progressBar=20;
}
}]);
I want progressBar value form ListController2 to be reflected back in Listcontroller1. It seems i am doing something wrong with it. Please help any one. thank u.

Rather than sharing state with $routeScope, you should consider creating a service to share the state of the progress bar - this is one of the use cases of services.
When the save button is pressed in the code below, it updates the value in progressService. The value from progressService is watched in the first controller and the view is updated accordingly.
You can add progressService to as many controllers as you'd like.
var app = angular.module("app", []);
app.factory("progressService", [function() {
var service = this;
service.progressBar = 0;
return service;
}]);
app.controller("ListController1", ["$scope", "progressService", function($scope, progressService) {
progressService.progressBar=10;
$scope.progress = progressService.progressBar;
$scope.$watch(
function() {
return progressService.progressBar;
},
function(newValue) {
$scope.progress = newValue;
});
}]);
app.controller("ListController2", ['$scope','progressService',function($scope,progressService) {
$scope.save=function() {
progressService.progressBar=20;
}
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="ListController1">
Progress: {{progress}}
</div>
<div ng-controller="ListController2">
<button ng-click="save()">Save</button>
</div>
</div>

Related

Passing Object from One Controller to Another AngularJS

I need to pass an object from one controller to another and have used this solution but it is not working.
Here the code:
angular.module("customerApp", [])
.controller('MainCtrl', function ($scope, myService, $http, $location) {
var vm = this;
vm.pinFormCheck = function () {
vm.count++;
if (vm.pinForm.$valid && vm.details.PIN === vm.pin && vm.count <= 2) {
location.href = "http://localhost:51701/Home/MainMenu";
$scope.obj = {
'cid': 'vm.details.CID',
'name': 'vm.details.Name',
'pin': 'vm.details.PIN',
'bal': 'vm.details.Bal',
'status': 'vm.details.cardStatus'
};
console.log(vm.details.Bal);//the correct balance get displayed in console
} else {
vm.failPin = true;
}
};
})
.controller('CheckCtrl', function ($scope, myService) {
$scope.data = myService.getObj();
})
.factory('myService', function () {
var obj = null;
return {
getObj: function () {
return obj;
},
setObj: function (value) {
obj = value;
}
}
});
Here is the view from which the first object is passed:
<body ng-app="customerApp">
<div ng-controller="MainCtrl as vm">
<form name="vm.pinForm">
<input type="password" ng-model="vm.pin" ng-required="true" />
<p><button ng-disabled="vm.count >=3" ng-click="vm.pinFormCheck();" ng-init="vm.count=0">Proceed</button></p>
</form>
...
Here' the second view where I need the object
<html ng-app="customerApp">
<body ng-controller="CheckCtrl">
<div>
<h1>your balance is {{data.bal}}</h1>
....
The balance from vm.details.Bal from the first view must appear in data.bal in the second view, but nothing is appearing.
You can just save vm.details in some factory.
And then get it in CheckCtrl from this factory.
Factories in AngularJS implement singleton pattern. So saved data will be kept in until your app exists.
You tried to do next thing myService.getObj(); But you didn't save anything to the service.
Inject myService to the MainCtrl and then save details into it.

Factory value not updated in model ...what I am doing wrong?

I am new to angular-js. I have two controllers (welcomeContoller,productController) and both handling the same model within the factory.
When the model getting updating by one controller(productController) it should reflect the update in another controller. (welcomeContoller)
But its not happening now.
HTML code :
<body ng-app="myApp">
<div ng-controller="welcomeContoller">
{{totalProductCnt}}
</div>
<div ng-controller="productController">
<div class="addRemoveCart">
<span class="pull-left glyphicon glyphicon-minus" ng-click="removeProduct()"></span>
<span class="pull-right glyphicon glyphicon-plus" ng-click="addProduct(1)"></span>
</div>
</div>
JS code
var myApp = angular.module("myApp", ['ui.bootstrap']);
myApp.factory("productCountFactory", function() {
return {
totalProducts:0
};
});
myApp.controller("welcomeContoller", function($scope, productCountFactory)
{
$scope.totalProductCnt = productCountFactory.totalProducts;
});
myApp.controller("productController", function($scope, productCountFactory) {
$scope.addProduct = function() {
productCountFactory.totalProducts++;
alert(productCountFactory.totalProducts);
};
$scope.removeProduct = function() {
if(productCountFactory.totalProducts >=1)
productCountFactory.totalProducts--;
alert(productCountFactory.totalProducts);
};
});
Even after the addProduct is called the totalProductCnt is displaying as zero. I want to display the value for each increment.
Plunkr Link
Put the factory object reference on scope:
myApp.controller("welcomeContoller", function($scope, productCountFactory) {
$scope.productCountFactory = productCountFactory;
});
Watch the property of the object.
{{productCountFactory.totalProducts}}
The DEMO on PLNKR.
By putting a reference on scope, on every digest cycle the watcher looks up the value of the property and updates the DOM if there is a change.
The totalProductCnt from your welcomeController isn't updated because it is assigned only once when the controller is created.
You can use several solutions to refresh the displayed value. Use a getter for your totalProducts in the factory :
myApp.factory("productCountFactory", function() {
var totalProducts = 0;
return {
getTotalProducts: function() {
return totalProducts;
},
addProduct: function() {
totalProducts++;
},
removeProduct: function() {
totalProducts--;
}
};
});
myApp.controller("welcomeContoller", function($scope, productCountFactory) {
$scope.getTotalProducts = productCountFactory.getTotalProducts;
});
myApp.controller("productController", function($scope, productCountFactory) {
$scope.addProduct = function() {
productCountFactory.addProduct();
};
$scope.removeProduct = function() {
if (productCountFactory.getTotalProducts() >= 1)
productCountFactory.removeProduct();
};
});
And update the view accordingly:
<div ng-controller="welcomeContoller">
{{getTotalProducts()}}
</div>
Plunkr Link

Can you reuse $scope.$watch

I found some code I want to copy / paste and use in two controllers. It watches something.
$scope.$watch('thing', function (thing) {
// do cool stuff with thing
}
Instead of copy/paste, I'd like to put it in a service and use the service from both controllers sortof like this:
angular.module('myApp')
.factory('CoolService',
function () {
$scope.$watch('thing', function (thing) {
// do cool stuff with thing
}
}
Now if I do this, it won't know what $scope is, right? (According to some reading, it won't let me do that anyway.)
Nevertheless, I'd like to say, If you have this service, you get this watch.
There's a hint I can do this: Passing current scope to an AngularJS Service
So I took his example, fixed it, and scope.watch works in there, but now I can't set other scope variables inside the watch. I just don't know enough javascript to do it, but I'm close. I really think it will work with the right syntax...
angular.module('blah', []);
angular.module('blah').factory('BlahService', function() {
//constructor
function BlahService(scope) {
this._scope = scope;
this.myFunc = function(){
this._scope.otherVar = this._scope.someVar;
};
this._scope.$watch('someVar', function(someVar) {
// do cool stuff with thing
_scope.otherVar = this._scope.someVar; // undefined
this._scope.otherVar = this._scope.someVar; // undefined
this.myFunc(); // undefined
BlahService.prototype._someFunction(); // works, but...
return someVar;
});
}
//wherever you'd reference the scope
BlahService.prototype._someFunction = function() {
if (this._scope['someVar'] == 1) // undefined
this._scope['someVar']++;
}
return BlahService;
});
angular.module('blah').controller('BlahCtrl', function($scope, BlahService) {
$scope.someVar = 4;
$scope.BlahService = new BlahService($scope);
});
angular.module('blah').controller('Blah2Ctrl', function($scope, BlahService) {
$scope.someVar = 6;
$scope.BlahService = new BlahService($scope);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html ng-app="blah">
<body>
<div ng-controller="BlahCtrl">
1a. <input ng-model="someVar">
1b. <input ng-model="otherVar">
</div>
<div ng-controller="Blah2Ctrl">
2. <input ng-model="someVar">
2b. <input ng-model="otherVar">
</div>
</body>
</html>
The key feature that this snippet has is that the scopes are different scopes. It doesn't act like a singleton.
Passing $scopes to a service sounds like a recipe for memory leaks. If nothing else it's the long way around.
Instead consider just doing this in each directive:
scope.$watch('thing', function (thing) {
coolService.doCoolStuffWith(thing);
}
Let the directive do the watching of its own scope, and put the shared functionality in the service.
This did it, and it allows me to set other members of the scope from within the watch:
angular.module('blah', []);
angular.module('blah').factory('BlahService', function() {
//constructor
function BlahService(scope) {
this._scope = scope;
this.myFunc = function() {
this._scope.otherVar = this._scope.someVar;
};
this._scope.$watch('someVar', function(newValue, oldValue, scope) {
// do cool stuff with thing
scope.otherVar = Number(scope.someVar) + 1;
return newValue;
});
}
return BlahService;
});
angular.module('blah').controller('BlahCtrl', function($scope, BlahService) {
$scope.someVar = 4;
$scope.BlahService = new BlahService($scope);
});
angular.module('blah').controller('Blah2Ctrl', function($scope, BlahService) {
$scope.someVar = 6;
$scope.BlahService = new BlahService($scope);
});
<html ng-app="blah">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<div ng-controller="BlahCtrl">
1a. <input ng-model="someVar">
1b. <input ng-model="otherVar">
</div>
<div ng-controller="Blah2Ctrl">
2. <input ng-model="someVar">
2b. <input ng-model="otherVar">
</div>
</body>
</html>

passing ng-show between two different controllers

I have a button which falls into Controller B and two block of HTML code which kind of falls under controller A...............and button falls into one block of HTML code
Example:
<div ng-controller="A">
<div ng-show="now">
<div>
<Button ng-controller="B"></Button>
</div>
</div>
<div ng-show="later">
</div>
</div>
On one button click I show up now block and later on button click of B controller I kind of hide now block and display later block.
How do I achieve this functionality?? I am not able to pass ng-show varibales between two different controller files......what should I use???
Hope this helps...!
angular.module('app', [])
.controller('A', function($scope) {
console.log('A');
$scope.state = {
now: true
};
$scope.showLater = function() {
$scope.state.later = true;
};
})
.controller('B', function($scope) {
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="A" ng-app="app">
<div ng-show="state.now">
<div>
<button ng-controller="B" ng-click="showLater()">Show Later</button>
</div>
</div>
<div ng-show="state.later">LATER
</div>
<p> <pre ng-bind="state | json"></pre>
</p>
</div>
You could use a simple service that stores the state.
Example:
angular.module('mymodule').service('ActiveService', function() {
var service = {};
var status = false;
service.getStatus = function() {
return status;
}
service.toggle = function() {
status = !status;
}
return service;
})
And in your controller:
angular.module('mymodule').controller('SomeController', function(ActiveService) {
$scope.status = ActiveService.getStatus;
})
The Angularjs service is a singelton, so it will hold your values for you across different controllers, directives or pages.
Could also be used directly:
// Controller
$scope.service = ActiveService;
// Html
<div ng-show="service.getStatus()">
...
</div>
You can also achieve this by declaring the variable in $rootScope and watching it in controller A,
app.controller('A', function($scope, $rootScope) {
$rootScope.now = true;
$rootScope.later = false;
$rootScope.$watch("now", function() {
$scope.now = $rootScope.now;
$scope.later = !$rootScope.now;
})
});
In Controller B, you just change the value of now based on previous value like this on ng-click,
app.controller('B', function($scope, $rootScope) {
$scope.testBtn = function() {
$rootScope.now = !$rootScope.now;
}
});
I have implemented a button within different divs(now and later) in a plunker,
http://embed.plnkr.co/xtegii1vCqTxHO7sUNBU/preview
Hope this helps!

AngularJS: how to modify an array in the service from multiple controllers

I want to have an array in the service, which can be modified from different controllers.
The purpose of this is the have an array accessible through every controller.
I want to be able to push items to this array from controllers, as well to delete them.
Service:
.service('EmailOps', function () {
var templates = [];
return {
pushToEmailBody: function (newObj) {
templates.push(newObj);
console.log(templates);
}
};
});
Controller:
angular.module('app')
.controller('mainCtrl', function ($scope, $rootScope, EmailOps) {
$scope.include = EmailOps.pushToEmailBody;
});
HTML:
<div ng-controller="mainCtrl">
1
2
3
</div>
To summarize, I would like to be able to add multiple new elements to the array in the service by clicking on these links. Currently when it adds one of them, it replaces the one added before, so that I have an array with one element only. Any idea what I might be doing wrong?
please see here : http://jsbin.com/gesirira/1/edit
service:
app.service('EmailOps', function () {
var templates = [];
function pushToEmailBody (newObj) {
templates.push(newObj);
console.log(templates);
}
return {
templates:templates,
pushToEmailBody : pushToEmailBody
};
});
controller:
app.controller('firstCtrl', function($scope,EmailOps){
$scope.include = function(obj)
{
EmailOps.pushToEmailBody(obj);
};
$scope.temp = EmailOps.templates;
});
html:
<body ng-app="app">
<div ng-controller="firstCtrl">
1
2
3
<br/>
templates: {{temp |json}}
</div>
</div>
</body>
You can modify your service like this
.service('EmailOps', function () {
this.templates = [];
this.pushToEmailBody = function (newObj) {
templates.push(newObj);
console.log(templates);
}
});
and then in the controller :
$scope.include = function(obj)
{
EmailOps.pushToEmailBody(obj);
};

Resources