I have two controllers. The first one sets a variable into my service and my second one is supposed to get this variable, but it's undefined.
Aren't angular services supposed to be singletons ? Because my service seems to be instantiated for each controller.
Here's my code :
First controller
angular.module('myApp').controller('HomeCtrl', ['$scope', 'User', function ($scope, User) {
$scope.join = function () {
User.setRoom("test");
console.log(User.getRoom()); // displays 'test'
$window.location.href = '/talk';
}
}]);
In my second controller, I've just a
console.log(User.getRoom()); // displays ''
And here's my service
angular.module('myApp').factory('User', function () {
var data = {
room: ''
};
return {
getRoom: function () {
return data.room;
},
setRoom: function (room) {
data.room = room;
}
};
});
Do you have an idea?
You are using $window.location.href = '/talk'; to navigate - this triggers a full page reload, and all services are therefore also reinitialized.
You probably want to use the $location service. See the documentation and/or this answer for a summary of the difference between the two.
Related
My first controller:
angular.module('application')
.controller('FirstController',['$rootScope',function($rootScope) {
var data=[0,1,2];
$rootScope.items=data;
}]);
My second controller:
angular.module('application')
.controller('SecondController',['$rootScope',function($rootScope) {
$rootScope.items[0]=3;
console.log($rootScope.items); // [3,1,2]
}]);
When the second controller is running, its corresponding view is changed; however not the same happens when going back to the corresponding view of the first controller (both views are bound to $rootScope.items). Why that happens? I am using ui-router and FirstController has to do with the main page of the SPA and SecondController with another page. Moreover, by keeping track of $rootScope.items with:
<pre>
{{$root.items | json}}
</pre>
in both templates the second one is renewed to [3,1,2] and the first one remains [0,1,2].
Passing the same $scope between the two controllers isn't an ideal way of maintaining a single data model, and what you need to do is to establish a service module (or a factory) to manage the data for you, so that both controllers can talk to the factor for your data.
This is how you set up the factory
app.factory("Data",
function () {
var storage = [0,1,2]; // where your data is
return {
get: function () {
return storage;
},
set: function (toSet) {
storage = toSet;
return storage;
}
};
});
to let the controllers know where the data is, use
app.controller ("FirstController",
function ($scope, Data)
{
console.log(Data); // [0,1,2]
Data.set( [3,1,2]); // demoing change
}
same is for the second controller
app.controller ("FirstController",
function ($scope, Data)
{
console.log(Data); // [3,1,2]
}
I'm new to AngularJS, I want to pass dynamic value (username) from one controller in one module to another controller in another module. Routing and other things are working fine.
This is my code
loginModule.js
(function() {
var app = angular.module("waleteros", ["ngRoute","ui.bootstrap","ngCookies"]);
app.config(function($routeProvider) {
$routeProvider
.when("/",{
templateUrl:"views/login.html",
controller:"LoginCtrl"
})
}
})
app.js
(function() {
var app = angular.module("waleterosAdmin", ["ngRoute","ngGrid","ui.bootstrap","ngCookies"]);
app.config(function($routeProvider) {
$routeProvider
.when("/home",{
templateUrl:"homepage.html",
controller:"HomeCtrl"
})
}
})
loginCtrl.js
(function(){
var app = angular.module("waleteros");
var LoginCtrl= function($scope,$location)
{
$scope.signIn=function(email,pin)
{
//Some authentication code...
//Here i want to pass the username to homectrl.js
window.location.href="views/home.html"
}
}
app.controller("LoginCtrl", LoginCtrl);
})
HomeCtrl.js
(function(){
var app = angular.module("waleterosAdmin");
var HomeCtrl=function($scope)
{
//Here i want to get the username
}
app.controller("HomeCtrl", HomeCtrl);
})
you can share service between modules ,and thus pass value between modules,
please have a look here Share a single service between multiple angular.js apps ,and here sharing between modules with AngularJS?
You would use a service to persist the data, and then inject the service into your controllers:
app.service("SharedProperties", function () {
var _userName = null;
return {
getUser: function () {
return _userName
},
setUser: function(user) {
_userName = user;
}
}
});
Now inject SharedProperties and use the getter/setter
var LoginCtrl= function($scope,$location, SharedProperties)
{
$scope.signIn=function(email,pin)
{
//Some authentication code...
SharedProperties.setUser(user);
//Here i want to pass the username to homectrl.js
window.location.href="views/home.html"
}
}
var app = angular.module("waleterosAdmin");
var HomeCtrl=function($scope, SharedProperties)
{
//Here i want to get the username
var user = SharedProperties.getUser();
}
One word of warning about services is that they persist for the lifetime of the application, i.e. they are only instantiated once. I have run into scenarios, especially once routing is implemented, where I want to wipe the data off of the service to save space and replace it with new data (you don't want to keep adding to this service every time you look at a different view). To do this, you could either write a "wipe" method that you call to clean the service on the route changes, or stick the data into a directive (on its controller), put the controllers into their own directives, and have these require the first directive, so that the data is accesible from the controller's with the added benefit of being wiped once the DOM element is declared on is destroy (on a view change, for instance).
I created a service to share some data between two controllers. The thing is that this controllers set and get some data from this service. But I don't know why when I try to get data, all this variables are not set.
My code is this one:
var appModule = angular.module('app', ['mgcrea.ngStrap'])
// custom service to share/collect data between controllers
// this objects are populated by the controllers
.service('sharedProperties', function () {
this.searchPattern = {
basicFilters: {},
advanceFilters: {}
};
});
// controller for main section
appModule.controller('parentController', function ($scope, $aside, sharedProperties) {
$scope.basicFilters = {
category: 'undef',
masterbrand: {value:'undef', text: 'Any'},
page: 1,
perPage:10,
q:''
};
// populate object in service
$scope.updatePatternSearch = function(newValue, oldValue, scope) {
sharedProperties.searchPattern.basicFilters = 'HI!, I have a value!';
};
$scope.$watch('basicFilters', 'updatePatternSearch', true);
// get variables from service
$scope.search = function() {
// ** PROBLEM **
// firebug says that is:basicFilters: {},
// advanceFilters: {}
// empties????, why??
console.log(sharedProperties.searchPattern);
}
}
});
There are lots of typos and erros in your plnkr code.
I have forked and updated it. It's working fine.
Have a look at this - http://plnkr.co/edit/BVFjufOQFFlhB2gTqIeB?p=preview
I have an Angular app with several controllers. I would like each controller to maintain its state even when the user navigates to another controller and back again. Essentially I want each view to load up just as the user last saw it (unless they navigate away from the app entirely or refresh etc.).
I understand how to share state between controllers using a service but this is not what I want. I could create a new service for every controller or put everything on the $rootScope but it seems wrong.
What is the recommended way to do this?
I would store any persistent data in the $cookieStore and maybe even encapsulate it in a service to avoid remembering what the interface to the cookie actually is. Here's an example:
var app = angular.module('app', [
'ngRoute',
'ngCookies'
]);
app.service('ticketService', function ($cookieStore) {
this.getTicket = function () {
var ticket = $cookieStore.get('currentTicket');
// Check server for ticket? (additional business logic)
return ticket;
};
this.setTicket = function (ticket) {
// Validate correct ticket? (additional business logic)
$cookieStore.set('currentTicket', ticket);
};
});
app.controller('ticketController', function ($scope, ticketService) {
var defaultTicket = {
name: '',
description: ''
};
$scope.ticket = ticketService.getTicket() || defaultTicket;
$scope.$watch('ticket', function (oldValue, newValue) {
if (oldValue === newValue) { return; }
ticketService.setTicket(newValue);
});
});
Plunkr
I have this service I inject in my controllers. It is simply a service to share some properties.
angular.module('app', []).
service('sharedProperties', function () {
var list_name = '';
return {
getListName: function() {
return list_name;
},
setListName: function(name) {
list_name = name;
}
};
});
I have two controllers. In the first one, I set the value of list_name. In my second, I want to retried this information.
Here is how are defined my controllers :
function ListCtrl($scope, $http, sharedProperties) {
...
$scope.changeListName = function(list_name) {
sharedProperties.setListName(list_name);
console.log(list_name, sharedProperties.getListName()); # shows ( 'metro', 'metro') == metro being a dummy list_name
...
};
function ItemCtrl($scope, $http, sharedProperties) {
...
$scope.showOnlyList = sharedProperties.getListName();
console.log(this.sharedProperties.getListName()); # empty string
...
};
I logged the variable and checked them in the browser console and noticed that ListCtrl sets the shared Property properly. The issue comes from the ItemCtrl controller. It seems that when I try to access the list_name with sharedProperties.getListName();, the property is empty, or the function returns an empty string.
UPDATE
I thought the problem came from the service. So I decided to use Lungojs' data library.
I got the following code :
In ListCtrl :
$scope.changeListName = function(list_name) {
Lungo.Data.Cache.set("ListName", list_name);
console.log('LIST', Lungo.Data.Cache.get("ListName"));
};
In ItemCtrl :
$scope.showOnlyList = Lungo.Data.Cache.get("ListName");
console.log('ITEM', Lungo.Data.Cache.get("ListName"));
The log in ListCtrl shows that the cache is set to the correct list_name. However, the console for ItemCtrl shows that Lungo.Data.Cache.get("ListName") is undefined even if it was correct on the ListCtrl!
I also tried replacing the cache by HTML5 local storage without success...
Well, I think its because you instantly log your sharedListPropery to the console, right after instantiating your ItemCtrl.
When it is instantiated, sharedPropertyList has no value yet.
EDIT:
Sry, JSFiddle is currently not working, so I have to put this untested code here.
But it should give you an idea
angular.module('app', []).
service('sharedProperties', function () {
var list_name = '';
return {
getListName: function() {
return list_name;
},
setListName: function(name) {
list_name = name;
}
};
}).
controller('ListCtrl',['$scope','sharedProperties',function(scope,shared){
console.log(shared.getListName()); //empty, because nothing set yet.
scope.listname = shared.getListName();
//watching the change and updating the shared
scope.$watch('listname',function(value){
console.log('listname is now '+value);
shared.setListName(value);
})
//watching the shared directly
scope.shared=shared;
scope.$watch('shared.getListName()',function(value){
console.log("sharedProperty has changed to"+value);
})
}]);