I am using angularjs.
I am making simple $http.delete method call in my API for deleting row from grid table:
My controller looks like below:
$scope.removeRow = function(detail, index){
var delRes = $http.delete($scope.appUrl + detail.id);
delRes.success(function (data, status, headers, configs) {
console.log(data);
delete $scope.appDetails[index].id;
});
delRes.error(function (data, status, headers, configs) {
console.log(data);
});
};
Now, API call works fine but I can still see record in my grid on UI.
When i refresh the page i can not see.
Any reason.
Please help.
It seems to me like you are only deleting the id property of the appDetails's index row.
Try deleting the whole appDetails[index].
If that is not your problem you can try using $scope.$apply() with the proper checks before calling it. Works on async calls.
If you're creating an AngularJS service (such as for sockets) it
should have a $scope.$apply() anywhere it fires a callback.
$scope.$apply() should occur as close to the async event binding as
possible.
https://github.com/angular/angular.js/wiki/When-to-use-$scope.$apply()
You can delete the selected index itmes by using splice
Best Way
Please try this
$scope.removeRow = function(detail, index){
var delRes = $http.delete($scope.appUrl + detail.id);
delRes.success(function (data, status, headers, configs) {
console.log(data);
var index = $scope.appDetails.indexOf(detail);
$scope.appDetails.splice(index, 1);
});
delRes.error(function (data, status, headers, configs) {
console.log(data);
});
};
Another way is
Rebind | reload the $scope.appDetails value
$scope.removeRow = function(detail, index){
var delRes = $http.delete($scope.appUrl + detail.id);
delRes.success(function (data, status, headers, configs) {
console.log(data);
//Rebind the scope value
$scope.appDetails=data;// like call the grid load function
});
delRes.error(function (data, status, headers, configs) {
console.log(data);
});
};
Related
I have a function
var getData = function() {
$http.get('(url of remote site)/swi/20?expand=true').success(function (data) {
$scope.listOfServices = data.runningServices;
});
};
Which updates every 30 seconds and pulls of a list of services.
HOWEVER i would like to expand this to also pull from
$http.get('(url of remote site)/**pad**/20?expand=true')
and $
http.get('(url of remote site)/**bri**/20?expand=true')
for example and then MERGE the rusults (all in exactly the same format) into ONE $scope
How can I merge these HTTP gets with three different endpoints in the URL?
EDIT: Following the link in the first comment I have come up with THIS
var getData = function() {
var swindon = $http.get('(url)/swi/10?expand=true'),
paddington = $http.get('(url)/pad/10?expand=true'),
reading = $http.get('(url)/rdg/10?expand=true');
$q.all([swindon,paddington,reading]).then(function(arrayOfResults) {
$scope.listOfServices = arrayOfResults;
console.log($scope.listOfServices);
});
};
getData();
but the problem is now is that I have an array of arrays that I simply cannot access in any way. I have even done a repeat within a repeat
Here is a screenshot of Google COnsole with the logged scope
I normally loop over the listOfServices.trainServices
FINAL EDIT:
Got it, used the loop within a loop properly i.e
<tbody ng-repeat="item in listOfServices">
<tr ng-repeat="service in item.data.trainServices">
You can nest the calls, like this:
$scope.listOfServices = [];
$http.get('(url of remote site)/swi/20?expand=true')
.success(function (data, status, headers, config) {
$scope.listOfServices.concat(data.runningServices);
$http.get('(url of remote site)/pad/20?expand=true')
.success(function (data, status, headers, config) {
$scope.listOfServices.concat(data.runningServices);
//nest Another and so on...
//$http.get('(url of remote site)/bri/20?expand=true')..
});
})
.error(function (data, status, headers, config) {$scope.listOfServices = [];});
Or use a resolved promises as in the answer below:
angular -- accessing data of multiple http calls - how to resolve the promises
I am consuming this Rest web service from my AngularJS application and I'm using $resource to pass parameters and get my data.
I have a particular service that can take the same parameter multiple times like this in my Postman session:
/myService/Accounts?acctId[]=7029&acctId[]=3324
I've tried to pass a generated string to my $resource query methods placeholder but it ends up escaping all my brackets and not working.
I also tried not using a placeholder and passing the same parameter twice, it doesn't fail but it takes the last value so that does not work either.
$scope.resultsColl = rfpService.searchAccountName.query({
acctName: $scope.accountName,
acctRole: acctRoleParams,
acctRole: acctRoleParams2
});
Hopefully someone has had this same issue? Any ideas?
From the research I've done on other posts it looks like you can't dynamically generate using $resource. My working solution was to switch to $http, this way I could dynamically generate multiple acctRole[] params:
var acctRoleParams = '';
if(corporate === true)
{
acctRoleParams = '&acctRole[]=C';
};
if(smallBiz === true)
{
acctRoleParams += '&acctRole[]=B';
};
$http.get("https://myRestServiceUrl/services/customer/accounts?acct=" + $scope.account + acctRoleParams)
.success(function (data, status, headers, config) {
$scope.gridOptions.data = data.data.detailsByAcct;
})
.error(function (data, status, headers, config) {
showToast("An error occurred during the request");
})
.finally(function () {
$scope.isGridLoading = false;
});
I wanted to post this in case anyone else has been struggling to do the same thing.
When a user logs into the main page of my site, I typically load quite a bit of data on the home page. much more than when they come to a specific url on the page. When they hit the ome page, that actually fullfills the data requests of much of the data that I grab individually when they hit a specific page.
I like how the $http module works with $cache and I'm wanting to use the knowledge of my home page hit to populate the cache of calls I know the individual page will make.
That is, as an example, my home page calls /rest/clients which returns all clients while individual pages call /rest/client/101. What I want to do is make it so that if /rest/clients is called first, then when /rest/client/101 is called an new fresh xhr call does not have to be made but the data can be gotten from the cache as if /rest/client/101 had already been called.
I've never done a decorator before but I'm thinking maybe a decorator on the $http service? I looked through the $http code and it seemed the cache is stored in closure to the actual http call and not exposed except on the next Get.
Has anyone done this or similar? I could not find it. Any specific pseudo coding suggestions would be very welcome.
In your data service you have 2 methods, getAll and getOne.
In the service define a reference to your getAll results promise.
Then in your getOne service check to see if that promise exists and if it does use it to filter out the one item that you need to satisfy your getOne need.
module.service('dataService', function($http){
var getAllPromise = null;
this.getAll = function(){
if (getAllPromise !== null){
getAllPromise;
}
getAllPromise = $http.get('clients');
return getAllPromise
};
this.getOne = function(id){
if (getAllPromise !== null){
return getAllPromise
.then(function(allData){
//logic here to find the one in the full result set
return theFoundItem;
};
}
return $http.get('clients/' + id);
};
});
I found the solution I asked for but implementing and making it testable is proving to be beyond my skills. I'm going to go with #brocco solution but for the permanent record I'm leaving the actual answer to what I was asking. I'm not marking this as the correct solution because #brocco solution is better for my real problem. So, thank you #brocco for the help.
You can see below what I'm basically doing is to create my own $cache with $cacheFactory. I then use the .put method of the new cache object to prime my cache. Then, subsequent calls to the client/1 url will get the cache'd record without ever having to call cache/1 in real live. The cache is loaded in the for loop from the first big call.
Thanks for everyones input on this.
var myApp = angular.module('myApp', []);
myApp.factory('speakersCache', function($cacheFactory) {
return $cacheFactory('speakersCacheData');
});
myApp.controller('personController', ['$scope','$http','speakersCache', function ($scope,$http,speakersCache) {
$scope.getAllSpeakers = function() {
$http.get('speakers.json',{cache: speakersCache}).
success(function (data, status, headers, config) {
debugger;
var i;
for(i=0;i<data.length;i++) {
var url = 'speaker/' + i;
speakersCache.put(url, data[i]);
}
}).
error(function (data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
};
$scope.getAllSessions = function() {
$http.get('sessions.json',{cache: speakersCache}).
success(function (data, status, headers, config) {
debugger;
}).
error(function (data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
};
$scope.getOneSpeaker = function() {
$http.get('speaker/1',{cache: speakersCache}).
success(function (data, status, headers, config) {
debugger;
}).
error(function (data, status, headers, config) {
debugger;
});
}
$scope.checkit = function() {
var x = speakersCache;
debugger;
};
}]);
If I understand you well, I have done something similar:
I have this code:
.factory('myOwnEntity', ['$filter',
function ($filter) {
var myOwnList = [];
return {
set : function (data) {
myOwnList = data;
},
get : function () {
return myOwnList;
},
find : function (id) {
return $filter('filter')(myOwnList, { itemId : id }).pop();
}
}
}
])
When I make the petition to the Web Service, I store the information like this:
$http.get(url, {
cache : true
})
.success(function (data) {
myOwnEntity.set(data);
defer.resolve(data);
});
return defer.promise;
Now, the next time I need some information, I just query my entity with the find method. Hope this is what you are looking for.
I have an array of ids and would like to iterate over them and pass them to a service to fetch some data. But I would like to only move to the next id after the processing of the previous id has finished. After all the data has been fetched I need to call a specific function.
My code (without the iteration) wold be something like
MyService.fetch(id)
.success(function (data, status, headers, config) {
doSomething();
});
What I want to achieve is something like this but in a way which can handle an unknown number of items in my array of ids:
MyService.fetch(id).success(function (data, status, headers, config)
{
MyService.fetch(id2).success(function (data, status, headers, config)
{
doSomething();
});
});
Any ideas how to achieve this ?
thanks
Thomas
Angular comes with a lite promise library: $q.
It's actually quite simple to do.
Service
myApp.factory('theProcessor', function($q, $timeout) {
return {
fetch: function(queue, results, defer) {
defer = defer || $q.defer();
var self = this;
// Continue fetching if we still have ids left
if(queue.length) {
var id = queue.shift();
// Replace this with your http call
$timeout(function() {
// Don't forget to call d.resolve, if you add logic here
// that decides not to continue the process loop.
self.fetch(queue, results, defer);
results.push({ id: id, value: Math.floor((Math.random()*100)+1) });
}, 500);
} else {
// We're done -- inform our caller
defer.resolve(results);
}
// Return the promise which we will resolve when we're done
return defer.promise;
},
};
});
See it in action at this plunker.
Try to use following approuch:
var idsArray= [], result = [];
/// ...After filling array
function nextIteration(index) {
MyService.fetch(idsArray[index]).success(function (data, status, headers, config)
{
result.push(data);
if (++index < idsArray.length) {
nextIteration(index)
} else {
console.log('Task complete');
}
}
nextIteration(0);
You could use the $q's all() method to bundle all the promises that you define and then do something after all of them are resolved e.g:
$q.all([promise1, promise2, ...]).then(...)
You may want to consider implementing this feature in your controller or your service.
Take a look at HERE for a complete API reference and details.
UPDATE
Just thinking that your service could accept an array of ids and it could have a method which would recursively fetch the data in order that you want. Look and the following code, it's an idea so it may not work as is:
function(){
var result = [];
var fetch = function(idArr /*this is your ID array*/){
(a simple guess if what you want to do with that ID)
$http.get('yourURL?id=' + <first element of idArr>)
.success(function(data){
//some logic
result.push(data);
idArr.splice(1,0);
fetch(idArr);
});
}
}
I have have spent hours trying all of the different methods given online but nothing works. I just simply want to load a script to run after all images have loaded. Is there something about Angular that won't allow me to do this? I'm using $routeProvider:
var photos = {
name: 'photos',
url: '/photos',
views: {
main: {
templateUrl: "views/photos/photos.html",
controller: function($scope,$http){
$http({
url: 'get/photos',
method: "POST"
})
.success(function (data, status, headers, config) {
$scope.data = data;
// this doesn't work
$(window).load(function() {
myScript();
});
})
.error(function (data, status, headers, config) { $scope.status = status; });
}
}
}
};
By the way, I'm not getting any errors in the console.
It seems to me that the http POST call retrieves the photos. And I am suppose that myScript is a function. So why not try this:
var photos = {
name: 'photos',
url: '/photos',
views: {
main: {
templateUrl: "views/photos/photos.html",
controller: function($scope,$http){
$http({
url: 'get/photos',
method: "POST"
})
.success(function (data, status, headers, config) {
$scope.data = data;
myScript();
})
.error(function (data, status, headers, config) {
$scope.status = status;
});
}
}
}
};
since the myScript function only runs after the POST succeeds. I am supposing that the data refers to the actual image data.
I don't know if I really understood what type of data you are trying to get, but I think you could try with promises
$http in Angular already return a promise wrapped in .success or .error, but you can also use the .then() callback like with every other promise
So if the problem is to wait for the success() callback to be finished you could do something this way, replacing it by several then() :
$http.post(...).then(
//function which will wait for the data to be downloaded
//here you can alter data, check some values etc...
).then(
//the script for what you want after
myScript();
);
I made a little fiddle to explain : http://jsfiddle.net/Kh2sa/2/
It simulates a long response time with $timeout, so you have to wait 3 secondes to see your modified data, which remains in its initial state until you call the myScript() function
AFAIK, Angular does not provide a way to inform us when images have finished loading.
You will need to write your own directive for this. The directive would wrap the necessary JavaScript/jQuery code that would detect the finished loading condition for one or more images.
jQuery callback on image load (even when the image is cached) and https://github.com/desandro/imagesloaded might help.