Basically I have this controller:
angular.controller('AddUsersCtrl', function ($scope, UsersService) {
$scope.users = [];
function toggleUser (user) {
user._toggled = !user._toggled;
}
function addAll ()
var users = $scope.users;
UsersService
.addMany(users)
.success(function (response) {
// ...
})
}
});
It is the controller of a page where users can add multiple users at once, and each users can be toggled (basically it the toggled is the UI state which is used by the view to toggle user information)
But as you can see, the addAll function refers to the users on the scope and then calls a "addMany" method from UsersService. At this point somehow the _toggled variable should be filtered out because else it will also send "_toggled" to the backend.
Now a simple solution would be to loop through the users and remove the "_toggled" variable, but is there a better way or is my structure wrong?
You could use a separate array for your attribute, like this:
angular.controller('AddUsersCtrl', function ($scope, UsersService) {
$scope.users = [];
$scope.toggledUsers = {};
function toggleUser (user) {
$scope.toggledUsers[user] = !$scope.toggledUsers[user];
}
function addAll ()
var users = $scope.users;
UsersService
.addMany(users)
.success(function (response) {
// ...
})
}
});
Related
(function () {
angular.module("app").controller('DashboardController', ['$q', 'dashboardService', function ($scope, $q,dashboardService) {
var DashboardController = this;
dashboardService.loadFromServer(DashboardController );
console.log("DashboardController ", DashboardController);
}])
})();
angular.module("app").service('dashboardService', ['$http', '$q', function ($http, $q) {
return {
loadFromServer: function (controller) {
var getDashboardEntries = $http.get('http://someUrl');
var getEmailData = $http.get('http://someOtherUrl');
var getSidebarData = $http.get('http://yetAnotherUrl');
return $q.all([getDashboardEntries, getSidebarData, getEmailData])
.then(function (results) {
controller.dashboardData = results[0].data;
controller.chartData = results[1].data;
controller.emailData = results[2].data;
});
},
};
}]);
1.The service returns the three bits of data and this is the results when logged using:
console.log("DashboardController ", DashboardController);
When I try to drill down on the data in this manner it logs "undefined"
console.log("DashboardController "DashboardController.dashboardData);
console.log("DashboardController "DashboardController.chartData);
console.log("DashboardController "DashboardController.emailData);
Do you realize that console.log is executed right after invoking loadFromServer before the server has chance to respond and promise resolves? The actual order is:
loadFromServer
console.log
promise success method - where you actually have your data
Change your controller's code to this:
dashboardService.loadFromServer(DashboardController ).then(function() {
console.log("DashboardController ", DashboardController);
});
What would be even better is to construct some object from parts of responses and assign it in the controller itself - not the service. In current implementation if you wanted to have another controller then service would assign response parts to same fields. I'd propose sth like this:
return $q.all([getDashboardEntries, getSidebarData, getEmailData])
.then(function (results) {
var data = {
dashboardData = results[0].data;
chartData = results[1].data;
emailData = results[2].data;
};
return data;
});
and then in controller:
dashboardService.loadFromServer().then(function(data) {
DashboardController.dashboardData = data.dashboardData;
DashboardController.chartData = data.chartData;
DashboardController.emailData = data.emailData;
});
In this solution the controller decides what to do with data, not the other way around.
I have a angular service function that is being called multiple times.
In the index.html page I have the following line:
<li><i class="pull-right"></i><br/>{{appCtrl.service.getCurrentUser()}} </li>
In the application controller I set the variable
appCtrl.controller('AppController', function ($state, securityService, $log) {
$log.info('App controller');
var appCtrl = this;
appCtrl.service = securityService;
});
In my service I exposed the function
login.factory('securityService', function ($window, $log) {
var currentUser;
return {
setCurrentUser: function (user) {
currentUser = user;
$window.sessionStorage.setItem('User', JSON.stringify(currentUser));
},
getCurrentUser: function () {
$log.info('Calling current user');
if (!currentUser) {
var storedObject = $window.sessionStorage.getItem('User');
currentUser = JSON.parse(storedObject);
}
return currentUser;
}
}
});
The following line in the getCurrentUser function gets called multiple times when the application starts up or page refresh is being done.
$log.info('Calling current user');
The controller is being called only once, I monitor it by looking at $log.info('App controller');
Is it being called as part of the dirty checking process or am I doing something wrong?
Angular calls your function on every digest cycle, you can set breakpoint inside the function and check it. If you are on 1.3 version, then please take a look at One Time Binding feature. If not then call the service inside the controller and bind view to some scope variable:
$scope.currentUser = securityService.getCurrentUser();
And inside view bind to scope variable:
{{currentUser}}
Try this, this is correct factory declaration. Because internally AngularJS calls yout factory like: securityService(injects); , each time you inject (use) your factory.
login.factory('securityService', function ($window, $log) {
var currentUser;
return {
setCurrentUser: function (user) {
currentUser = user;
$window.sessionStorage.setItem('User', JSON.stringify(currentUser));
},
getCurrentUser: function () {
$log.info('Calling current user');
if (!currentUser) {
var storedObject = $window.sessionStorage.getItem('User');
currentUser = JSON.parse(storedObject);
}
return currentUser;
}
};
});
I've been struggling with this for a few days now and can't seem to find a solution.
I have a simple listing in my view, fetched from MongoDB and I want it to refresh whenever I call the delete or update function.
Although it seems simple that I should be able to call a previously declared function within the same scope, it just doesn't work.
I tried setting the getDispositivos on a third service, but then the Injection gets all messed up. Declaring the function simply as var function () {...} but it doesn't work as well.
Any help is appreciated.
Here's my code:
var myApp = angular.module('appDispositivos', []);
/* My service */
myApp.service('dispositivosService',
['$http',
function($http) {
//...
this.getDispositivos = function(response) {
$http.get('http://localhost:3000/dispositivos').then(response);
}
//...
}
]
);
myApp.controller('dispositivoController',
['$scope', 'dispositivosService',
function($scope, dispositivosService) {
//This fetches data from Mongo...
$scope.getDispositivos = function () {
dispositivosService.getDispositivos(function(response) {
$scope.dispositivos = response.data;
});
};
//... and on page load it fills in the list
$scope.getDispositivos();
$scope.addDispositivo = function() {
dispositivosService.addDispositivo($scope.dispositivo);
$scope.getDispositivos(); //it should reload the view here...
$scope.dispositivo = '';
};
$scope.removeDispositivo = function (id) {
dispositivosService.removerDispositivo(id);
$scope.getDispositivos(); //... here
};
$scope.editDispositivo = function (id) {
dispositivosService.editDispositivo(id);
$scope.getDispositivos(); //... and here.
};
}
]
);
On service
this.getDispositivos = function(response) {
return $http.get('http://localhost:3000/dispositivos');
}
on controller
$scope.addDispositivo = function() {
dispositivosService.addDispositivo($scope.dispositivo).then(function(){
$scope.getDispositivos(); //it should reload the view here...
$scope.dispositivo = '';
});
};
None of the solutions worked. Later on I found that the GET request does execute, asynchronously however. This means that it loads the data into $scope before the POST request has finished, thus not including the just-included new data.
The solution is to synchronize the tasks (somewhat like in multithread programming), using the $q module, and to work with deferred objects and promises. So, on my service
.factory('dispositivosService',
['$http', '$q',
function($http, $q) {
return {
getDispositivos: function (id) {
getDef = $q.defer();
$http.get('http://myUrlAddress'+id)
.success(function(response){
getDef.resolve(response);
})
.error(function () {
getDef.reject('Failed GET request');
});
return getDef.promise;
}
}
}
}
])
On my controller:
$scope.addDispositivo = function() {
dispositivosService.addDispositivo($scope.dispositivo)
.then(function(){
dispositivosService.getDispositivos()
.then(function(dispositivos){
$scope.dispositivos = dispositivos;
$scope.dispositivo = '';
})
});
};
Being my 'response' object a $q.defer type object, then I can tell Angular that the response is asynchronous, and .then(---).then(---); logic completes the tasks, as the asynchronous requests finish.
I need to show the name of current user in the top bar of my website. The user data should be disappeared when user logout. I used the following two services:
app.factory('Auth', ['$resource', function ($resource) {
return $resource('/user/login');
}])
.service('CurrentUser', [function () {
this.user= null;
}]);
Here is my login and topbar controllers.
app.controller('LoginCtrl', ['CurrentUser', 'Auth', '$location', function (CurrentUser, Auth, $location) {
this.login = function () {
var me = this;
me.user = Auth.save(me).$promise.then(
function (res) {
CurrentUser.user = res;
$location.path("/");
}, function (res) {
me.errors = res.data;
});
}
}])
.controller('TopBarCtrl', ['CurrentUser', function (CurrentUser) {
var me = this;
me.user = CurrentUser;
}])
Using this controllers and services in had to use {{contoller.user.user.name}} to show the user's name. Is there any way to use {{contoller.user.name}} instead and keep the two-way bindings?
You would have to use
me.user = CurrentUser.user;
As your are setting the result of your http.save in the first then to the .user property of CurrentUser.
What does the server result, e.g json, look like?
Newbie here!)
I have this service:
angular.module('autotestApp').service('GroupPageService', function () {
var group = "";
this.list = function () {
return group;
};
this.update = function (new_group) {
group = new_group;
};
});
and this controller:
angular.module('autotestApp').controller('GroupPageController', function ($scope, $http, $routeParams, GroupService, $modal, GroupPageService) {
$scope.groupId = $routeParams.id;
$scope.group = GroupPageService.list();
var getGroup = function (id) {
$http({
method: "get",
url: "/enterprises/_groups/"+id
}).success(function (response) {
GroupPageService.update(response.group);
}).error(function () {
console.log("Error while fetching data of one particular group")
});
};
getGroup($scope.groupId);
}
My logic is:
getGroup() function fetches data from web API and updates the variable "group" in the service
$scope.group is assigned to data that is returned by service.list() function
Data is being returned from the web API correctly but there is a problem with the rest.
The variable $scope.group is not being updated
How to fix this?
You can watch for a service method using $watch.
$scope.$watch(function() {
return GroupPageService.list();
}, function(newValue, oldValue) {
if (newValue !== oldValue) {
$scope.group = GroupPageService.list();
}
}, true);
You need to assign the data that you get back from the API in your success method. The first assignment you do for $scope.group at the top only get executed when the controller runs for the first time. There is nothing updating the contents of $scope.group afterwards.
Regarding services: You generally use services when you want to share data across your app. In your case if you want to retrieve those groups once and then inject your service into multiple controllers and have that data available.
It seems that when you assign a new value in your service you are changing the reference to that value. What you should do for your code to work is transform your group variable into an object:
app.service('GroupPageService', function () {
var group = {name: "xxx"} ;
this.list = function () {
return group;
};
this.update = function (new_group) {
group.name = new_group;
};
});