In my voting app I'm just updating a simple ng-repeat with calls to my API to create, and delete polls. I had this working perfectly when all of my $http calls were in my controller but when I try to modularize my code with a service it doesn't update properly.
I don't fully understand promises, but I did some searches on here to see if that would work, but I didn't make any progress..
Service:
/* global app */
app.factory("pollsService", ["$http", function($http){
return {
get: $http.get('api/polls').success(function(data) {return data;}),
deletePoll: function(id, cb) {
$http.delete('/api/polls/' + id)
.success(function(results) {
cb(results);
})
.error(function(err) {
throw err;
});
},
createPoll: function(formData, cb) {
$http.post('/api/polls', formData)
.success(function(results) {
cb(results);
})
.error(function(err){
throw err;
});
}
}
}]);
Controller:
/* global app */
app.controller("mainController", ["$scope", "pollsService", function($scope, pollsService){
$scope.formData = {};
pollsService.get
.success(function(results){
$scope.polls = results;
})
.error(function(err){
alert(err);
})
$scope.removePoll = function(id) {
pollsService.deletePoll(id, function(results){
$scope.polls = results;
})
}
$scope.createPoll = function() {
pollsService.createPoll($scope.formData, function(results){
$scope.polls = results;
$scope.formData = {};
})
}
}]);
My calls still work but I have to refresh the browser to get my updated data when I click on the newly created poll, or delete a poll.
Any help would be much appreciated!
I would suggest using service structure instead of factory. Also why don't you use $resource service? It could be solved easily with this approach:
/* global app */
angular.service("pollsService", function($resource){
this.get = get;
this.deletePoll = deletePoll;
this.createPoll = createPoll;
function get(){
return $resource('api/polls', {}).query().$promise;
}
function deletePoll(params){
return $resource.delete('/api/polls/:id', {id: params.id}).remove().$promise;
}
function createPoll(formData){
return $resource.post('/api/polls', {}).save(formData).$promise
}
})
---- CTRL
app.controller("mainController", ["$scope", "pollsService", function($scope, pollsService){
$scope.formData = {};
pollsService.get().then(function(data){
$scope.polls = results;
}, function(error){
})
$scope.removePoll = function(id) {
pollsService.deletePoll({id: id}).then(function(results){
$scope.polls = results;
}, function(error){
// error here
})
}
$scope.createPoll = function() {
pollsService.createPoll($scope.formData).then(function(data){
$scope.polls = results;
$scope.formData = {};
}, function(error){
});
}
}]);
in order for ng-repeat to update the existing view with your new data - you will need to add $scope.$apply(); after the data has been updated.
Hope this helps.
Related
js1.js
app.controller('test1Controller',
function($scope,$http,$ngBootbox,$location,CRUDService,NotificationService,constants,ngWizard) {
$scope.fun1 = function(){
$http.get(context+"/back/demande/rest/test1").success(function(data, status) {
$scope.dto = data;
});
};
});
js2.js
app.controller('test2Controller',
function($scope,$http,$ngBootbox,$location,CRUDService,NotificationService,constants,ngWizard) {
$scope.fun2 = function(){
$http.get(context+"/back/demande/rest/test2").success(function(data, status) {
$scope.dto = data;
});
};
});
How can I call fun1 => js1.js in js2.js?
First, you need to move your function to angular.js service instance.
Then you need to inject this service to your controllers, like NotificationService.
Then you can call in different controllers.
app.service('myHttpService', ['$http', function($http) {
this.getData = function(context, endpoint) {
return $http.get(context+"/back/demande/rest/" + endpoint);
};
}]
// do not forget to use injector if you don't have ngAnnotate
app.controller('test2Controller', function($scope, $http, $ngBootbox, $location, CRUDService, NotificationService, constants, ngWizard, myHttpService) {
$scope.dto = null;
$scope.fun2 = function(){
myHttpService.getData(context, 'test1')
.then(function(data, status) {
$scope.dto = data;
});
};
});
I have a factory that request user data via an api call:
angular.module('MyApp')
.factory('UserApi', function($auth,Account){
return {
getProfile: function()
{
Account.getProfile()
.then(function(response){
return response.data; ----> returning json data ok!!
});
}
}
});
But when i call the function in controller, it return me undefined
myApp.controller('AppCtrl', function($rootScope,$state,$window,$document,$scope,$filter,$resource,cfpLoadingBar,$translate,UserApi){
$scope.user = function(){
UserApi.getProfile().then(function(data){
$scope.currentUser = data;
})
}
console.log($scope.user()); ----> undefined
});
account factory:
angular.module('MyApp')
.factory('Account', function($http){
return {
getProfile: function(){
return $http.get('/api/me');
}
}
});
The error that log in console is TypeError: Cannot read property 'then' of undefined
EDIT
The only available solution is to set the response.data to $rootScope.user in which the data will be available across the controllers.
angular.module('MyApp')
.factory('UserApi', function($auth,Account,$rootScope){
return {
getProfile: function()
{
Account.getProfile()
.then(function(response){
$rootScope.user = response.data; ----> returning json data ok!!
});
return $rootScope.user;
}
}
});
First of all getProfile method should return a promise (not undefined like it's doing in your code):
angular.module('MyApp')
.factory('UserApi', function($auth,Account){
return {
getProfile: function()
{
return Account.getProfile()
.then(function(response) {
return response.data;
});
}
}
});
then in controller you should use then callback:
myApp.controller('AppCtrl', function ($rootScope, $state, $window, $document, $scope, $filter, $resource, cfpLoadingBar, $translate, UserApi) {
$scope.user = function () {
UserApi.getProfile().then(function (data) {
$scope.currentUser = data;
console.log($scope.currentUser);
})
};
});
Also make sure you understand the difference between synchronous and asynchronous code, and why console.log($scope.user()) makes no sense in this case: response if not yet available when you try to log it. Instead you provide a callback to be called when data has come.
You are trying to return the data after the request is completed successfully. But, since this is an ajax call we don't know when it will be completed (Basically, runs on a different thread.). There are two ways you can resolve this.
1 - Just return the call like so.
angular.module('MyApp')
.factory('UserApi', function($auth,Account){
return {
getProfile: function(){
return Account.getProfile(); // return call and resolve in controller.
}
}
});
2 - You can use promise ($q)
angular.module('MyApp')
.factory('UserApi', function($auth,Account, $q){
return {
getProfile: function(){
var deferred = $q.defer();
Account.getProfile()
.success(function(data){
deferred.resolve(data);
});
return deferred.promise; // just return the promise
}
}
});
and in your controller just have the following.
myApp.controller('AppCtrl', function($rootScope,$state,$window,$document,$scope,$filter,$resource,cfpLoadingBar,$translate,UserApi){
$scope.user = function(){
UserApi.getProfile().then(function(data){
$scope.currentUser = data;
console.log($scope.currentUser);
});
}
});
EDITED:
You get undefined. Because:
there isn't return in $scope.user
your console.log($scope.user($scope.user()) works only initial time.
there is time delay for getting data from UserApi.getProfile()
Also, your codes have some mistakes:
I can suggest that:
Don't use your console.log($scope.user()) initial time.
Or, You should get all data initial time when factory created. Then, you use UserApi.data in your controller.(But, there is time delay. You may get success data, if request return response before from loading of your controller).
.
angular.module('MyApp')
.factory('UserApi', function ($auth, Account) {
var data;
Account.getProfile().then(function (response) {
data = response.data;
});
return {
data: data
}
});
myApp.controller('AppCtrl', function ($rootScope, $state, $window, $document, $scope, $filter, $resource, cfpLoadingBar, $translate, UserApi) {
console.log(UserApi.data);
});
i have used Angularjs and i wanna call getcustomer function from one controller to another controller i have so many doing gooogling but i don't have an idea that how to call that
i have write below code which i used
var app = angular.module('Napp', []);
app.controller('GetAlphabetical', function ($scope, $http) {
function getCutomers() {
$scope.loading = true;
$http.get('#Url.Content("~/Home/GetPesrons")').then(function (response) {
//var _data = angular.fromJson(response);
$scope.loading = false;
$scope.Customer = response.data; // please check the request response if list id in data object
}, function (error) {
throw error;
})
}
});
and second controller :
app.controller('MainCtrl', function ($scope, $http) {
getCutomers()
});
Mate, you will have to follow the following steps to resolve your problem. Firstly you have you create a factory
angular
.module('Napp')
.factory('CustomerFactory', ['$http', function ($http) {
var _factory = {};
_factory.getCustomers = function () {
return $http.get('#Url.Content("~/Home/GetPesrons")');
};
return _factory;
}]);
Then you can share data and functions between multiple controllers or services
GetAlphabetical Controller :
angular
.module('Napp')
.controller('GetAlphabetical', ['$scope', 'CustomerFactory', function ($scope, CustomerFactory) {
loadCustomers();
function loadCustomers() {
CustomerFactory.getCustomers().then(function (successResponse) {
$scope.Customer = successResponse.data; // please check the request response if list id in data object
}, function (errorResponse) {
throw error;
})
}
}]);
MainCtrl Controller :
angular
.module('Napp')
.controller('MainCtrl', ['$scope', 'CustomerFactory', function ($scope, CustomerFactory) {
loadCustomers();
function loadCustomers() {
CustomerFactory.getCustomers().then(function (successResponse) {
$scope.Customer = successResponse.data; // please check the request response if list id in data object
}, function (errorResponse) {
throw error;
})
}
}]);
This can be easily done by defining it as a service and injecting it as a dependency.
var app = angular.module('myApp', []);
myApp.service('helloWorldFromService', function() {
this.sayHello = function() {
return "Hello, World!"
};
});
app.controller('MainCtrl', function ($scope, $http, helloWorldFromService) {
app.controller('GetAlphabetical', function ($scope, $http, helloWorldFromService) {
Angular Service
What you want to do is to somehow communicate between two controllers. This can be easily be achieved using $broadcast & $on.
Incase there is a parent child relation between your controllers, use the following.
function firstCtrl($scope){
$scope.$broadcast('someEvent', [1,2,3]);
}
function secondCtrl($scope){
$scope.$on('someEvent', function(event, mass) {console.log(mass)});
}
If there is no parent child relationship between your controller, then inject $rootScope and broadcast using that.
related question - https://stackoverflow.com/a/14502755/1182982
I have seperated out my controllers & services into modules, and on a form submit, I am trying to get data from a service and then set it in the scope, but I'm having trouble getting the view to update with the new data. I have gone through other questions with similar problems but I can't seem to get it working. The view updates fine from the Search.get() function, but not from the $scope.submitFilterForm function.
I'm trying to update like this:
$scope.searchDetails = results;
This is my code at the moment:
SearchCtrl.js
angular.module('SearchCtrl', []).controller('SearchController', function($scope, $http, Page, Search) {
$scope.pageClass = 'page-search';
$scope.showContent = false;
$scope.searchDetails = [];
Search.get().success(function(searchResults) {
$scope.searchDetails = searchResults;
Page.setTitle('Search');
$scope.showContent = true;
});
$scope.submitFilterForm = function(isValid) {
if (isValid) {
Search.filterByPostcode($scope.postcode, $scope.searchradius).success(function(results) {
console.log('results', results);
$scope.searchDetails = results;
});
}
}
});
SearchService.js
angular.module('SearchService', []).factory('Search', ['$http', function($http) {
return {
get: function() {
return $http.get('/api/places');
},
filterByPostcode: function(postcode, searchradius) {
return $http.get('/api/filter-by-postcode/'+postcode+'/'+searchradius);
}
}
}]);
search.html
<div class="places-list" ng-show="showContent">
<div class="places-list-item" ng-repeat="place in searchDetails">
{{place.place_name}}
</div>
</div>
I also have the template above set up in appRoutes.js like so:
$routeProvider
// home page
.when('/search', {
title: 'Search',
templateUrl: '/partials/search.html',
controller: 'SearchController'
})
$locationProvider.html5Mode(true);
Thanks for any help.
I am currently working myself through tutorials and books teaching AngularJS.
I want to write a simple app, that loads some user data from a json file and displays it.
Now this is the relevant part of a JavaScript file, which does what I want:
Here is my Code :
angular.module('myModule', [])
.controller('myCtrl', function($scope, $http) {
$http.get('../mockdata/users_js.json').success(function(data, status, headers, config) {
$scope.users = data;
});
});
Now if I try to create a separate module for importing my data, I fail:
angular.module('myModule', [])
.controller('myCtrl', function($scope, Users) {
$scope.users = Users.query();
})
.factory('Users', function($http) {
var users = {};
users.query = function() {
// In real apps, we'd pull this data from the server...
$http.get('../mockdata/users_js.json').success(function(data, status, headers, config) {
this.data = data;
});
return this.data;
};
return users;
});
What am I doing wrong ?
And How can i fix this ?
In users.query() you kick off an asynchronous HTTP request, and then before it has a chance to finish return this.data which is undefined.
You could take a look at $resource, it returns a promise that you can assign to a $scope variable immediately. It will apply the right value when the request completes.
.factory('Users', function($resource) {
var users = {};
users.query = function() {
return $resource('../mockdata/users_js.json').get();
};
return users;
});
If you want to know how to do this with $http:
angular.module('myModule', [])
.controller('myCtrl', function($scope, Users) {
Users.then(function(data){
$scope.users = data;
});
})
.factory('Users', function($http) {
var Users = {};
Users = $http.get('../mockdata/users_js.json').then(function (response) {
return response.data;
});
return Users;
});
Here's a live Plnkr.