AngularJs $http get not working 1st time but does on subsequent invocations - angularjs

All:
I have an Iframe tag on a simple HTML page and inside this Iframe tag is a HTML form - lets call it a widget. Its a form where the user can enter search criteria and click on a button to obtain the search results. I have decided to use Angularjs to make the necessary DB calls to a REST service that returns the search results back to the widget for display.
In testing this I enter a value in a textbox on the widget, that value being a value that I know exists in a particular table I'm testing against.
Here is my $http get call:
$http
.get('http://localhost/XXXXService/folder/getfolders/' +
$scope.formData.srchterm **==>** mapped to search textbox
).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
//$scope.formData = response;
//$scope.nrdFolderDataArray = response;
console.log('Success retrieving data.');
console.log(response.length);
console.log('response:');
console.log(response);
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log('Error occurred retrieving data.');
console.log(response.status);
console.log('returned data count:');
console.log(response.size);
console.log('response:');
console.log(response);
});
This call is inside a function called "submitForm" that is mapped to the widget with a "ng-submit="submitForm()" attribute on the submit button. And yes there are several log statements so I can try and figure out what is going on here. And what is happening is this: after entering a value in the textbox, THE FIRST TIME the search button is clicked the .get command does not work. I does not make the call to the REST service. I know this because I wrote the REST service and made sure I put in plenty of log statements while doing so and there are no log statements in the log file from the REST service. Instead the errorCallback block runs and I see all those log statements in the console. The "response" (object?) after THE FIRST call looks like this:
Object {data: null, status: 0, config: Object, statusText: ""} Method = GET Status = (canceled) type xhr
Further, in FF there is no response data to view in the Net tab of Firebug upon THE FIRST call, but there is response data to view in all subsequent calls.
So, interestingly enough each subsequent invocation of that $http.get call works! I see log statements in the log file from the REST service method and the successCallback block runs and I can see my data via those console.log messages.
Also, if I were to change the search value in the text box, which would then be THE FIRST TIME we would be searching for data for that new key, once again, the call does not work, but does work on subsequent clicks on the "search" button for that new key value.
I really am not sure if I have a CORS issue here since, other than THE FIRST calls each subsequent $http.get call works like a champ. Its just that very first call or first call after the search key has changed that the $http.get does not want to work.
I have tried setting headers in the .get call and I have tried using
#CrossOrigin(origins = "http://localhost/7001") as per
https://spring.io/guides/gs/rest-service-cors/ but I continue to have this issue on the first time invoking this .get call.
I've been dealing with this issue for way too many hours now and would sure appreciate some input as to why this is happening.
I'm sorry for being verbose here. I wanted to explain my issue thoroughly.
Please help.
Thank you
-g

Related

How to keep displayed result before new search result display

Due to low query result, in my AngularJS application, when I click a search button to request a new search, my page will display my pre-define error message "No related search result as you want", after one/two seconds, my query finish, my page refresh to display my new search result.
I want to keep my displayed result before new search result display?
Any suggestion or hint to do that? Thanks.
This comes down to where you put the code to clear or replace the list of results.
It seems like you currently do something like this in your controller:
runSearch(searchText) {
this.results = []; // this shows your "no results" text
this.$http.get('/search?q=' + searchText).then(res => this.results = res.data);
}
Instead, just remove the first line so you only ever replace the results once the HTTP call returns:
runSearch(searchText) {
this.$http.get('/search?q=' + searchText).then(res => this.results = res.data);
}
Explanation
There are two points inside runSearch where Angular will update the page for you:
After the function is run, but before the HTTP call returns
After the HTTP call returns
Here they are in the code:
runSearch(searchText) {
// #1 - any code here will update the page immediately
this.$http.get('/search?q=' + searchText)
.then(function (res) {
// #2 - any code here will update the page when the HTTP call returns
});
// (#1 - if you have any code here it will also update the page immediately)
}
The technical reason for this is that Angular calls your runSearch() function inside a $scope.$apply() call, which calls your function and then runs a full digest of all the scopes in the application. That's what allows Angular to see the change and update the page. However, the function you pass to .then() on the $http promise executes some time later, after the initial digest completes. But Angular will also call this other function (the one passed to .then()) inside $scope.$apply(), which triggers another digest and allows Angular to see and apply any changes to the page at that time.
If you think about what you wanted to achieve, you only wanted to update the page after the search results are returned (#2 in the code above). So by only putting your code there, you got the page to update at the correct time, not before.

AngularJS and Ionic click to repeat a failed http request

I'm making an app using AngularJS and Ionic.
When my app sends a request to the server using $http and fails, I want a view to load to show the user a button which, when clicked, repeats the $http request that was just attempted.
Currently if the request fails, it will load an error view, but I want that error view to have a button which performs a repeated task when clicked. This will be the same error controller for all server errors, so needs to be adaptable and have a way to pass in or repeat all functions easily in one place.
function getData(){
$http({
url: remoteUrl+'/dat/get_data_app',
method: 'POST',
data: {}
}).then(function(response) {
}, function(response) {
//the getData is trying to pass in the current function so it can be repeated in the error controller
$localstorage.setObject('httpObj', getData());
$state.go('app.error');
});
}
Below is the error controller currently:
.controller('ErrorCtrl', function($scope, $localstorage, $recipes) {
var httpObj = $localstorage.getObject('httpObj');
//this needs to run as a funtion (only when button is clicked but I can sort that out, just need a way of passing the function here)
httpObj;
})
The error controller runs when the user lands on the error page. In order to make the controller short and not need much changing later, I want the function passed here to run on click of a button which I'll place here.
Adding the button isn't the problem, but I just want to know if there's an easy way to pass the function.
This whole way of doing it may be wrong but any thoughts will be appreciated :)
Thanks

Why $http in ng-init is not getting called everytime the view is loaded - AngularJS

I have modified my question as per my observation.$http request on server side is not happening whenever the view is called second or third or so on times although initWishList (ng-init) is getting called. The scenario is as below:
I have a My Account tab in the nav-bar, which opens a view having options like MyWishlist, My Address etc. When My wishlist is clicked for the first time, $http request happens, but when I again click on My Account (this time I don't see any call on server side when the .html view is loaded) , and then if I click My Wishlist , the controller is called but $http isn't called (this time I again dont see any call on server side from $http) but I can see the alert Init Called
Why so?
$scope.initWishList = function(){
alert('Init called')
$http.get("/get_wish_list/")
.success(function (response) {
$scope.refreshWishList(JSON.parse(response["products_json"]));
})
.error(function(){
console.log('Error');
});
};
Hope I have explained the scenario properly.
Controllers gets intialized only once when angular parses ng-controller directive. Since controller is initialized once, ng-init will also run once.
For your satisfaction, add a break point in the your controller on the first line, see when you hit that break point. Are you hitting that break point, every time you click the tab ? If not, ng-init will not be called every time

$http.jsonp is not working properly

I have following $http call in controller:
see complete code in plunker
$http.jsonp("http://currencyconverter.kund.nu/api/availablecurrencies/?callback=JSON_CALLBACK")
.success(function(data){
console.log('data',data)
})
.error(function(err){
console.log('err',err)//it console err undefined
})
above code console err undefined. means it executing error callback.but when i open chrome network tool, in responses it is showing response data.Why it is like that ?
Your jsonp url should always have one parameter callback=JSON_CALLBACK which you are missing here
$http.jsonp("http://currencyconverter.kund.nu/api/availablecurrencies/?callbak=JSON_CALLBACK")
Update
Seems like server side you had not implemented the logic to wrap returned object inside value of callback, because hit this url in browser console should give array wrap inside JSON_CALLBACK variable
JSON_CALLBACK({..data here})
But it is returning an array
[...data...]
This behavior should be handled on server side.

How to use $resource in AngularJS properly for building a client app?

I've been following this tutorial http://draptik.github.io/blog/2013/07/28/restful-crud-with-angularjs/. I implemented a Grails backend with it instead of the Java one in the tutorial.
I've got the data coming back and forth, with one issue. If I create/update/delete a user, I don't see the changes reflected on my user list when I am redirected back. I have to refresh the page to see the updates.
Looking at the network traffic for an edit, it looks like it does a PUT and fires off the GET before the PUT is complete. Assuming this is because $resource returns a promise so things can be done asynchronously. So how do I handle this so that when $location redirects me, my list is up to date?
I'm guessing the options are to wait for the PUT to complete before redirecting/querying for the list, or to somehow manually manage the $scope.users to match the request?
Or maybe this tutorial is just a bad example? Maybe there is a better way to do it (still using $resource)?
Note: I've seen Restangular out there, and I've seen $http with success callbacks, but I would like to understand the situation above.
One way to overcome this issue would be to not redirect to the list page, till you get a callback, and then do a redirect. You can show some busy indicator till that time. The resource call looks like this.
resource.update(config,data,function() { //gets called on success},
function(error) { //gets called on failure});
In real life scenario waiting for the response of update makes sense as you want to handle the error and success scenarios on the same page.
I don't see your code anywhere so i'm just assuming (based on what you wrote and your current problem)
You are probably doing a full (or partial) get each time you changed a user and (re)binding the result to your scope. Doing this in the callback of the resource should actually start the digest cycle angular does to update modified objects. If you had been doing the fetching outside $resource - for example with custom/jquery ajax you would need to execute $scope.$apply()
What i really don't understand you would need to wait for the callback. You already know you added/modified a user. Instead of 'detaching' that user from your scope, modify it, post it to your rest server, then wait for callback, and reinserting it into the scope - why not modify it directly in the list/array you put on your scope?
var users = Users.get(function () {
$scope.users = users.record; // bind the resulting records to the scope
});
$scope.updateUser = function (user) {
resource.update(...); //pseudo
};
Then in your html, you will keep a reference to the currentUser and the div-list will update automaticly.
<div ng-repeat="user in users" ng-click="currentUser=user">{{user.Name}}</div>
<input ng-model="currentUser.Name">
<button ng-click="updateUser(currentUser);">Update</button>
If you don't want to see the update in the list while you type, but only once your callback fires or when you hit the button, would would instead use another ng-model for your input like this:
<input ng-model="tempUser.Name">
And you would then copy the value other in either the updateUser method or in the resource callback like this:
$scope.updateUser = function (user) {
user.Name = $scope.tempUser.Name; // should update automaticly
resource.update(...) // pseudo
}
Hope it helped!

Resources