I have multiple queries in one controller, that load while the controller is loading (and after I click on some elements)
var d = $q.defer();
$scope.userOrders = UserOrders.query({id:$routeParams.id}, function(result) {
d.resolve(result);
});
$q.all([d.promise]).then(function(response){
$('#loading').hide();
});
How i can write this only once, not in each controller?
Encapsulate your ajax logic in a service
var services = angular.module('myServices', []);
services.factory('AjaxLoader', ['$q', function($q) {
return {
doAjax : function() {
var d = $q.defer();
$scope.userOrders = UserOrders.query({id:$routeParams.id}, function(result) {
d.resolve(result);
});
$q.all([d.promise]);
}
}
});
In your controller.
var controllers = angular.module('myControllers',[]);
controllers.controller('Controller', ['AjaxLoader', function(AjaxLoader) {
AjaxLoader.doAjax().then(function() {
$("#loading").hide();
});
}]);
Related
i'm new with both Angular & Firebase. I've been trying to create a factory to update my list of stations but the list just won't seem to update.
When i run the factory code firebase.database... in my controller it works fine though.
controller
.controller('DashCtrl', function ($scope,Stations) {
$scope.stations = [];
$scope.stations = Stations.getStations();
})
services
.factory('Stations', function() {
return {
getStations : function(){
firebase.database().ref('stations').once('value',function(snapshot){
console.log(snapshot.val());
return snapshot.val();
})
}
}
})
What am i doing wrong? Isn't the ng-repeat="(key,station) in stations" list supposed to change after the factory returns the new data ?
Also I've been noticing something in a few tutorials. What is the difference between the below 2 inits.
.controller('DashCtrl', function ($scope,Stations) {
$scope.stations = [];
$scope.stations = Stations.getStations();
})
.controller('DashCtrl', [$scope,Stations,function ($scope,Stations) {
$scope.stations = [];
$scope.stations = Stations.getStations();
}])
since you didn't wrap the firebase result with an Angular promise, the angular environment cannot notice there are new results arrived, you have two solutions:
using Angular Fire which provide angular bindings for firebase
wrap the return result with an $q promise:
//controller
.controller('DashCtrl', function ($scope,Stations) {
$scope.stations = [];
Stations.getStations().then(function(results){
$scope.stations = results;
});
})
//service
.factory('Stations', function($q) {
return {
getStations : function(){
var defer = $q.defer();
firebase.database().ref('stations').once('value').then(function(snapshot){
defer.resolve(snapshot.val());
}).catch(function(error){
defer.reject(error);
})
return defer.promise;
}
}
})
controller #1
.controller('DashCtrl', function ($scope,Stations) {
$scope.stations = [];
$scope.stations = Stations.getStations();
})
controller #2
.controller('DashCtrl', [$scope,Stations,function ($scope,Stations) {
$scope.stations = [];
$scope.stations = Stations.getStations();
}])
controller #2 is better for minification done by browsers which will result something like:
controller2.min.js
.controller('DashCtrl', [a,b, function(a,b) {
a.stations = [];
a.stations = b.getStations();
}])
I havea factory call HTTP end point to fetch user:
.factory('me', function($resource, VAS_API_URL, $q) {
return {
getUser: function() {
var deferred = $q.defer();
var url = VAS_API_URL + 'api/me';
$resource(url)
.get(function(user) {
deferred.resolve(user);
}, function(response) {
deferred.reject(response);
});
return deferred.promise;
}
};
})
I use this factory in many controllers and, i bind the data to the DOM successfully, but at times i want to use the data returned from the factory in my controller like to save the user name with a notification so i had to do the following:
.controller('createNotificationCtrl', function($scope, VAS_API_URL, me) {
var Burl = VAS_API_URL + 'api/notification';
$scope.profile = me.getUser();
$scope.profile.then(
function(user) {
$scope.owner = user;
$scope.item = {};
$scope.item.message = $scope.message;
$scope.item.owner = $scope.owner.displayName;
},
function(response) {
console.log(response);
}
);
})
I had to creat $scope.item = {}; in the factory call so i could get the displayName then send the object to save a notification but what if i want to save also another filed from another factory. How it could be done?
The factory should create the object and hold it as a state.
The controller's should use the reference from the factory and update it for everyone.
factory code sample:
this.stateObj = {};
....
....
this.getUser = function(){
var promise = $http.get(url);
promise.then(function(res){
// update stateObj
});
return promise;
}
ctrl code sample:
factory.getUser().then(function(res){
$scope.stateObj = factory.getStateObj();
});
I'm very new to AngilarJS. I am trying to write a service in angularJS.
<script>
var module = angular.module("myapp", []);
module.service('BrandService', function ($http) {
var brands = [];
this.getBrands = function()
{
return $http.get('http://admin.localhost/cgi-bin/brand.pl')
.then(function(response)
{
brands = response.brands;
alert (brands);
});
}
//simply returns the brands list
this.list = function ()
{
return brands;
}
});
module.controller("brandsController", function($scope, BrandService) {
$scope.brandlist = BrandService.list();
alert ($scope.brandlist);
});
</script>
The statement "alert (brands);" is not getting called. What is the issue with this code. Is m missing any thing in implementation?
$http calls are always async. Meaning, even you do a .then at your service, there is no way it will properly the resolved data back into your controller. You will have to write it in your controller.
Your Service:
module.service('BrandService', function($http) {
var brands = [];
this.getBrands = function() {
//do not need the dot then.
return $http.get('http://admin.localhost/cgi-bin/brand.pl')
}
//simply returns the brands list
this.list = function() {
return brands;
}
});
In your controller:
module.controller("brandsController", function($scope, BrandService) {
BrandService.list()
.then(function(response) {
$scope.brandlist = response.brands;
alert($scope.brandlist);
});
});
In service:
this.getBrands = function() {
$http.get('http://admin.localhost/cgi-bin/brand.pl').then(function(response) {
brands = response.brands;
alert(brands);
return brands;
});
}
In controller:
$scope.brandlist = BrandService.getBrands();
alert($scope.brandlist);
In my controller, I'm calling a factory that fetches data from an API, then in the success function, the data is passed to another function that loops through it and calls another factory each round in the loop. The data retrieved from the second factory is then mashed up with the data from the first factory in a new object, each round in the loop, and pushed to an array.
When I add the data to the $scope, the view is being updated as the data is being fetched, you can see that the items in the view are added one by one and not all in a bunch.
I also need to sort the data in the $scope before it hits the view.
Is there a way to do this when all actions are finished? – When all data is fetched.
app.controller('MyCtrl', function($scope, firstFactory, secondFactory) {
var objArray = [];
function doStuff() {
firstFactory.getData().success(function(data) {
doMore(data);
});
}
function doMore(data) {
$.each(data, function(key, value) {
secondFactory.getData(value).success(function(result) {
var obj = {
test: result.test,
test2: value.test
};
objArray.push(obj);
});
});
$scope.data = objArray;
}
});
For the second call you can use $q.all. This would get resolved only when all the calls are complete
function doMore(data) {
var promises = [];
$.each(data, function (key, value) {
promises.push(secondFactory.getData(value));
});
$q.all(promises).then(function (responseArray) {
$.each(responseArray, function (result) {
var obj = {
test: result.test
};
objArray.push(obj);
});
$scope.data = objArray;
});
}
You can chain promises. A promise in the chain is only run when the previous has executed, or you can even run promises in parallel and with $q.all wait for all promises to finish.
Here is a sample that might help you plunker:
var app = angular.module('plunker', []);
app.factory('dataFactory', function($http, $q) {
var getData = function() {
var combinedData = [];
var deferred = $q.defer();
$http.get('first.json')
.then(function(data) {
return data;
})
.then(function(data) {
firstData = data;
$http.get('second.json').then(function(secondData) {
angular.forEach(firstData.data, function(value, key) {
combinedData.push(value);
});
angular.forEach(secondData.data, function(value, key) {
combinedData.push(value);
});
deferred.resolve(combinedData);
});
});
return deferred.promise;
};
return {
getData: getData
};
});
app.controller('MainCtrl', function($scope, dataFactory) {
$scope.items = [];
var onSuccess = function(data) {
$scope.items = data;
};
var onError = function() {
console.log('error');
};
dataFactory.getData()
.then(onSuccess, onError);
});
Hi I have two controllers
pqsAppModule.controller('NotificationBoxController',function($scope,items) {
$scope.list = items.list();
})
and
pqsAppModule.controller('NotificationController',function($scope,items) {
$scope.list = items.list();
})
I need to create an "items" service that would do an ajax request and return data for any controller which would have it injected. And I want, that the query will be done only once, and items will be shared between all controllers.
pqsAppModule.factory('items', function($http) {
var items = [];
var itemsService = {};
$http.get('api/notification').then(function(response){
items = response.data;
});
itemsService.list = function() {
return items;
};
return itemsService;
});
But I don't understand why angular makes the request, and receives data, but all items in controllers are empty.
It happens because the factory should be defined by different way.
(I took dummy URL only to load data by async way)
HTML
<div ng-controller="NotificationBoxController">
<button ng-click="showMe();">press me</button>
<pre>NotificationBoxController: {{items.getList()|json}}</pre>
</div>
<div ng-controller="NotificationController">
<pre>NotificationController: {{items.getList()|json}}</pre>
</div>
JS
var pqsAppModule = angular.module('myApp', []);
pqsAppModule.controller('NotificationBoxController',function($scope,items) {
$scope.items = items;
$scope.showMe= function(){
items.query();
}
});
pqsAppModule.controller('NotificationController',function($scope,items) {
$scope.items = items;
});
pqsAppModule.factory('items', function ($http) {
var current = {};
var address = 'Singapore, SG, Singapore, 153 Bukit Batok Street 1';
var URL = 'http://maps.googleapis.com/maps/api/geocode/json?address=' + address + '&sensor=true';
var factory = {
query: function () {
var data = $http({method: 'GET', url:URL}).then(function (result) {
current = result.data.results[0];
}, function (result) {
alert("Error: No data returned");
});
},
getList: function () {
return current;
}
}
return factory;
});
Demo Fiddle
From this example we call items.getList() from HTML for both controllers. But if we want to update the model through the controller, we need a listener like $watch
Try this
$http.get('api/notification').then(function(response){
angular.foreach(response.data,function(item) {
items.push(item);
});
});
Basically do not create a new array but fill the existing one.