How can i pass variable values from one controller to another? [duplicate] - javascript

This question already has answers here:
AngularJS: How can I pass variables between controllers?
(16 answers)
Closed 7 years ago.
I have two different controller where i am trying to pass variable values to do some actions, I used $broadcast angularJS event but its not working. Is there any other solution to achieve this task ?
I understand there is already question asked regarding variables between controller but i wanted to know what are other possible soultions.
ctrl1.js
$scope.viewAssessmentFrmCycle = function(assessmentId) {
$scope.$broadcast('viewAssessment',assessmentId);
}
ctrl2.js
$scope.$on('viewAssessment',function(s,assessmentId){
console.log(assessmentId);
$location.path('/rcsa/editAssessmentFromCycle/'+assessmentId+);
});

Use a service.
angular.module('myApp', [])
.service('ShareThis', function () {
var value = 'myValue';
return {
getValue: function () {
return value;
},
setValue: function(newValue) {
value = newValue;
}
};
});
Then you can access this in each controller by either setting or getting...
Eg:
myApp.controller('Ctrl1', function($scope, ShareThis) {
$scope.value = ShareThis.getValue();
});
myApp.controller('Ctrl2', function ($scope, ShareThis) {
$scope.setVal = function(val) {
ShareThis.setValue(val);
}
}

You can create a factory to hold the data.
Factory:
angular.module('myModule').factory('commonData', function(){
var commonValue = {};
return {
getData : function(){ return commonValue },
setData : function(newData) { commonValue = newData }
}
});
Then inject this factory into your controller and use the set and get functions to manipulate the data.

Use factory to hold your data..
var app = angular.module('test', []);
// create a mediator factory which will persist the data
app.factory("MediatorFactory", function() {
return {
obj: {
value: ""
}
};
});
app.controller("FirstCtrl", ["MediatorFactory", function(mediator) {
this.variable1 = mediator.obj;
}]);
app.controller("SecondCtrl", ["MediatorFactory", function(mediator) {
this.variable2 = mediator.obj; // this.variable2 = this.variable1 in the controller1
}]);

Related

angularjs undefined object in service

I want to share data from controller 1 to another controller
I get an undefined error in my 2nd controller. Is anyone able to tell me whats wrong with my code?
Service
app.service('var_transfer_service', function(){
var test_var;
return {
getVar: function () {
return test_var;
},
setVar: function( _test_var ) {
test_var = _test_var;
console.log(test_var);//show the object content in my console
}
}
})
Controller 1
app.controller('homeCtrl', function($scope,$http, $filter ,var_transfer_service){
$scope.search_item = function ($event,item){
console.log(item)
var latt = item.lat;
var lngt = item.lng;
var_transfer_service.setVar(item);
}
});
Controller 2
app.controller('MapCtrl',function($scope,var_transfer_service, $state, $cordovaGeolocation) {
var transferred_var = var_transfer_service.getVar();
console.log(transferred_var); //undefined object
});
It's undefined because it's not initialized:
var test_var;
You only set a value on the setVar function which gets called in the $scope.search_item function in the secound controller (that you never call).
What is your indented behaviour?
You used a service, but wrote a factory.
Angular services return the function instance, so put functions on the function scope, using "this".
Using service:
app.service('var_transfer_service', function(){
var test_var;
this.getVar = function () {
return test_var;
};
this.setVar = function( _test_var ) {
test_var = _test_var;
console.log(test_var);//show the object content in my console
}
}
Basically, angular service returns the function itself, but factory return the return value of the function - so, you wrote a factory.
So your code would work, if you will use app.factory:
app.factory('var_transfer_service', function(){
var test_var;
return {
getVar: function () {
return test_var;
},
setVar: function( _test_var ) {
test_var = _test_var;
console.log(test_var);//show the object content in my console
}
}
})

Javascript Getter/Setter in Angular Service with 2 Controllers

I am messing with javascript getters and setters in my service layer. I am using 2 controllers. The first controller just displays some text. The second controller allows hiding it. I am trying to figure out why one method works while another does not.
Here is the working example:
var app = angular.module('plunker', []);
app.factory('data', function () {
var fac = [];
var state = false;
fac.hideIt = function (hide) {
state = hide;
};
fac.hidden = function() {
return state;
}
return fac;
});
app.controller('MainCtrl', function($scope, data) {
$scope.name = 'World';
$scope.hide = data.hidden;
});
app.controller('SecCtrl', function($scope, data) {
$scope.hideAbove = function () {
var hide = true;
data.hideIt(hide);
};
});
Here is the not working example:
var app = angular.module('plunker', []);
app.factory('data', function () {
var fac = [];
fac.hide = {
state: false,
get get() {
return this.state
},
set set(hide) {
return this.state = hide;
}
};
return fac;
});
app.controller('MainCtrl', function($scope, data) {
$scope.name = 'World';
$scope.hide = data.hide.get;
});
app.controller('SecCtrl', function($scope, data) {
$scope.hideAbove = function () {
var hide = true;
data.hide.set = hide;
console.log(data.hide.get)
}
});
HTML (shared by both)
<body>
<div ng-controller="MainCtrl">
<div ng-hide="hide()">
<p>Hello {{name}}!</p>
</div>
</div>
<div ng-controller="SecCtrl">
<div ng-click="hideAbove()">CLICK HERE </div>
</div>
</body>
So my question is why does using the getter and setters in the non-working block of code not work?
You should use a service rather than a factory for this. A factory's value is set to the return value of the function you pass to it. There is not really a concept of "this" in a factory ("this" probably points to the window object). "this" in a service points to the service instance.
app.service('data', function () {
this.state = false;
this.hide = {
get value() {
return this.state;
},
set value(hide) {
this.state = hide;
}
};
});
See in your html:
ng-hide="hide()"
The problem is simple you need to change hide property into method inside MainCtrl
$scope.hide = function() {
return data.hide.get;
}
DEMO
But you will say why the first example worked?
Because in the first example data.hidden does return function literal while the latter example just returns the value from getter.

angular watch object not in scope

I have a service in which values can change from outside Angular:
angularApp.service('WebSocketService', function() {
var serviceAlarms = [];
var iteration = 0;
this.renderMessages = function(alarms, socket) {
if (! angular.equals(serviceAlarms, alarms)) {
serviceAlarms = alarms;
iteration++;
}
};
this.getAlarms = function () {
return serviceAlarms;
};
this.iteration = function () {
return iteration;
};
this.socket = initSocketIO(this);
});
The initSocketIO function makes callbacks to this services renderMessages() function and serviceAlarms variable gets changed on a steady basis.
Now i am trying to watch for changes in this service like so:
controllers.controller('overviewController', ['$scope', 'WebSocketService', function ($scope, WebSocketService) {
$scope.$watch(
function () {
return WebSocketService.iteration();
},
function(newValue, oldValue) {
$scope.alarms = WebSocketService.getAlarms();
},
true
);
}]);
to no avail. The second function provided to $watch never gets executed except on controller initialization.
I have tried with and without true as third parameter.
You should use $rootScope.$watch (not $scope.$watch)
I ended up using the solution below since $watch didn't work as excpected.
I refactored the solution to use $rootScope in combination with:
angularApp.run(['$rootScope', function($rootScope){
$rootScope.socket = {};
$rootScope.socket.alarms = [];
$rootScope.socket.faults = [];
$rootScope.socket.renderErrors = function(faults, socket) {
var faultArray = [];
angular.forEach(faults, function(error) {
error.value ? faultArray.push(error) : null;
});
if (! angular.equals($rootScope.socket.faults, faultArray)) {
$rootScope.socket.faults = faultArray;
$rootScope.apply();
}
};
$rootScope.socket.renderMessages = function(alarms, socket) {
if (! angular.equals($rootScope.socket.alarms, alarms)) {
$rootScope.socket.alarms = alarms;
$rootScope.$apply();
}
};
$rootScope.socket.socket = initSocketIO($rootScope.socket);
}]);
Now i have my socket-updated-model in all scopes to use freely in controllers and views.
Controller example:
$scope.acknowledgeAlarm = function(alarm) {
$scope.socket.socket.emit('acknowledgeAlarm', {
hash:alarm.icon.hash,
id:alarm.id
});
};
View example:
<div ng-repeat="alarm in socket.alarms">
{{alarm.name}} {{alarm.icon.progress}}
</div>

Angular js , passing object from service

'use strict';
var app = angular.module('app');
app.factory('currTripService', function() {
var currtrip ='';
return{
setCurrTrip: function(trip){
currtrip = trip ;
},
getCurrTrip: function(){
return currtrip ;
},
}
});
app.controller('TripCreateController', function($scope, $location, Trip,currTripService) {
//The save method which is called when the user wants to submit their data
$scope.save = function() {
//Create the forum object to send to the back-end
var trip = new Trip($scope.trip);
console.log(trip);
currTripService.setCurrTrip(trip);
console.log(currTripService.getCurrTrip());
//Save the forum object
trip.$save(function() {
//Redirect us back to the main page
$location.path('/trip/day/1');
}, function(response) {
//Post response objects to the view
$scope.errors = response.data.errors;
});
}
});
app.controller('TripDayCreateController',function($scope,$routeParams,currTripService){
$scope.items=[];
$scope.trip = currTripService.getCurrTrip();
console.log($scope.trip.city);
// $scope.products = productService.getProducts();
$scope.addItem = function(item) {
$scope.items.push(item);
$scope.item = {};
}
});
When i click on /trip/new , its does the save in TripCreateController and set the trip object inside currTripService.
Then when redirected to TripDayCreateContoller the console.log(currTripService.getTrip()) , returns 'undefined'
Is it because Trip is an object ? How can i fix this ?
try this:
app.factory('currTripService', function() {
var currtrip = '';
var self = this;
return{
setCurrTrip: function(trip){
self.currtrip = trip ;
},
getCurrTrip: function(){
return self.currtrip ;
},
}
});
When you declare a function, this scope changes so currtrip was only existing in your getter/setter functions, but not outside.
The best way to do this is to use a class. Below is a an example of a class from CoffeeScript.
class currTripService
# storage object
#data = null
# get data
get: =>
return #data
# set data
put: (data) =>
#data = data
app.factory('currTripService', currTripService)
However if you want to do this without a class method then you can instead use something that would imitate a class:
var currTripService = function () {
// storage variable
var currTrip = null
// reference to this element
var _this = this
return{
// set this trip value
setCurrTrip: function(trip){
_this.currtrip = trip;
},
// get this trip value
getCurrTrip: function(){
return _this.currtrip;
},
}
}
app.factory('currTripService', currTripService);
Just a note: I put the function outside the factory to imitate how you'd typically call a class, but you can obviously just put all of the code in the function declaration.
app.factory('currTripService', function () {
// logic
});

Angular service not passing between controllers

I have two controllers on a parallel scope level I need to pass data between:
function TableRowCtrl($scope, $http, sharedProperties) {
console.log(sharedProperties.getProperty());
$scope.items = sharedProperties.getProperty();
}
and
function SideNavCtrl($scope, $http, sharedProperties) {
$scope.customers = undefined;
var temp = "cats";
$http.get('data/customers.json').success(function(data) {
$scope.customers = data;
temp = "dogs";
sharedProperties.setProperty(temp)
});
sharedProperties.setProperty(temp);
console.log(sharedProperties.getProperty());
}
I am trying to use a service to do this (via examples I have seen) :
angular.module('myApp', []).service('sharedProperties', function() {
var property = "Cats";
return {
getProperty: function() {
return property;
},
setProperty: function(value) {
property = value;
}
};
});
However - when I try and set the data in the SideNavCtrl http success function, it does not bubble out - the service still returns 'cats' as its value. From what I have read, services are supposed to be global, and setting data in them should be permanent (as is its purpose). What am I doing wrong, and how can I get data between these two controllers on the same scope?
The problem is your TableRowCtrl saves the result of a function in its scope variable. When the service itself changes, the value in the scope does not because at that point, it's a simple property. You can either expose your service directly in the scope or wrap $scope.items in a function instead:
function TableRowCtrl($scope, $http, sharedProperties) {
$scope.items = function() { return sharedProperties.getProperty(); };
}
// And in your view
{{ items() }}
Or
function TableRowCtrl($scope, $http, sharedProperties) {
$scope.shared = sharedProperties;
}
// And in your view
{{ shared.getProperties() }}
Edit: Simple plunkr here
Edit #2:
If the problem is a binding that isn't updated because of an asynchronous process, you can use $scope.$apply:
$http.get('data/customers.json').success(function(data) {
$scope.customers = data;
temp = "dogs";
sharedProperties.setProperty(temp)
if(!$scope.$$phase)
$scope.$apply();
});
Edit 3:
I've recreated your $http.get and updated the plunkr and it works. Based on what you are showing in your questions, it should work using function instead of regular properties.
#SimomBelanger already identified the problem. I suggest using objects rather than primitives, then you don't need to call functions in your view:
<div ng-controller="TableRowCtrl">items={{items.property}}</div>
<div ng-controller="SideNavCtrl">customers={{customers}}</div>
app.service('sharedProperties', function () {
var obj = {
property: "Cats"
};
return {
getObj: function () {
return obj;
},
setObjProperty: function (value) {
obj.property = value;
}
};
});
function SideNavCtrl($scope, $timeout, sharedProperties) {
$scope.customers = undefined;
var temp = "cats";
$timeout(function () {
$scope.customers = 'some data';
temp = "dogs";
sharedProperties.setObjProperty(temp);
}, 2000);
sharedProperties.setObjProperty(temp);
}
function TableRowCtrl($scope, $http, sharedProperties) {
$scope.items = sharedProperties.getObj();
}
fiddle
In the fiddle I use $timeout to simulate an $http response.
Because getObj() returns a (reference to an) object, updates to that object are automatically picked up by the view.

Categories

Resources