How can you call an ajax compatible WCF service inside a angular.js controller ?
I tried to combine Jquery and Angular.JS, something like :
app.controller('ListUsersController', function () {
var me = this;
this.listusers = [];
this.fill = function () {
$.getJSON("Contact.svc/getjemploye", function (data) {
me.listusers.push({id:"1",name:"Vinc"});
});
};
});
When I push the user inside the listusers, it look like the controller can't see I am adding something to the list, so it doesn't show the list again (In the html, I can't see the new user I just pushed).
Angular has its own set of Ajax callers.
$http({ method: "GET", url: "http://yoururlhere.com")
.success(function (response) {
alert("success!");
});
Related
I am working on modifying a web application built by someone else a few years ago. In it, he built an API function in JS which when called, will pull data from SharePoint. I am adding a feature to the application, and will need to do another API call to retrieve some different data. So far, I haven't been able to figure out how to modify the code so that it waits for the ajax call to complete. All of the research that I have done indicates that I should be using a callback to accomplish this, but I am not sure how to implement it properly.
The existing code looks like this:
API = function(apiFunction, dataToPost, successCallback) {
var baseApiUrl = '/SomeWebApp/API/';
var apiUrl = baseApiUrl + apiFunction;
$.ajax({
url: apiUrl,
data: JSON.stringify(dataToPost),
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function(data) { return data; },
success: successCallback,
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert('Error calling webservice: ' + apiFunction);
}
});
}
And the call to the API is:
API('Lists.asmx/GetStuff', dataToPost, function(data) {
var options = [];
$.each(data.d, function(index, value) {
options.push(new Category(value.Field, value.AnotherField, value.YetAnotherField));
});
var viewModel = new ViewModel(options);
ko.applyBindings(viewModel);
});
What I need to do is perform the second API call to retrieve the rest of the data, and then create the view model, passing it both sets of data.
What I've tried:
Moving options outside of the callback function, but it seems that because it is asynchronous, the script isn't waiting for the data to be returned. If it did work, I could move ko.ApplyBindings outside of the callback function, and just create the new view model with both sets of data
Assigning the API call to a variable, and having the callback function return options. For example:
var x = API('Lists.asmx/GetStuff', dataToPost, function(data) {
var options = [];
$.each(data.d, function(index, value) {
options.push(new Category(value.Field, value.AnotherField, value.YetAnotherField));
});
return options;
});
What would be the best way to modify the code to accomplish this? Should I create a wrapper function that includes the API function as a callback? How would I put that together?
The quick and dirty solution is to put the second API call within the callback function of the first API call. Return statements really don't do anything in an async function unless it's returning a "promise" (see option 2).
API('Lists.asmx/GetStuff', dataToPost, function(data) {
var options = [];
$.each(data.d, function(index, value) {
options.push(new Category(value.Field, value.AnotherField, value.YetAnotherField));
});
API('Lists/asmx/GetStuff2', secondDataToPost, function(data2){
var viewModel = new ViewModel(options, data2);
ko.applyBindings(viewModel);
});
});
Option 2 - since your API function is already using jQuery to handle the ajax you can change it to return the result of the ajax call, a type of deferred object, on which you can call .done to attach a callback method instead. jquery-deferred-and-promise walkthrough
API = function(apiFunction, dataToPost, successCallback) {
var baseApiUrl = '/SomeWebApp/API/';
var apiUrl = baseApiUrl + apiFunction;
return $.ajax({
...
});
}
The returned deferred object can be used similarly to the passed in callback by using the .done method on the object.
API('Lists.asmx/GetStuff', dataToPost).done(function(data) {
callback stuff...
});
This is a little more flexible and can let you do chaining and simultaneous execution like the following where both api calls get sent at the same time instead of having to wait for the response from the first call before sending the second one.
$.when(
API('Lists.asmx/GetStuff', dataToPost),
API('Lists.asmx/GetStuff2', dataToPost2)
).done(function(data1, data2) {
var options = [];
$.each(data.d, function(index, value) {
options.push(new Category(value.Field, value.AnotherField, value.YetAnotherField));
});
var viewModel = new ViewModel(options, data2);
ko.applyBindings(viewModel);
});
Been scratching my head for weeks on this particular part of my code. What I have is a simple custom service that would fetch my data via ajax, I then perform a post process and lastly I want to return that data back to my controller. Even tough my service is creating my object correctly nothing ever gets back to my controller.
Ive tried using a "deferred.promise" method, which does seems to return data back to the controller but in a $$state object that I cannot access via the controller for some strange reason. This is a whole other issue.
I just need a simpleway to return data to my controller but all of the post process must be handled in my service. Would anyone know if this is possible?
Here is what i got.
My service:
var app = angular.module('myApp', []);
app.factory('MyService', function($http, $q, $timeout){
var My_Stored_Data = {}
return {
load_my_data_service: function(){
$http({
method: 'GET',
url: 'AJAX PATH',
headers: { "Accept": "application/json;odata=verbose;charset=utf-8"}
}).then(function(data){
//post-process my data before returning it to the controller $scope.return_my_data_here
My_Stored_Data = data;
My_Stored_Data.data_result_1 = My_Stored_Data.data_result_1.split("\r\n");
My_Stored_Data.data_result_2 = My_Stored_Data.data_result_2.split("\r\n");
console.log(My_Stored_Data)//logs shows the that "My_Stored_Data" has processed my data correctly.
return My_Stored_Data //Return my data tot he controller $scope.return_my_data_here.
});
}
}
});
My controller:
app.controller('MyController', function ($scope,$q,MyService) {
$scope.fetch_my_data = function(){
$scope.return_my_data_here = MyService.load_my_data_service();
}
$scope.fetch_my_data() //Initiate on page load
});
#Ali Baig is correct. You need the return as he has pointed out. But the object returned is a promise and not the raw data as you are expecting so you also need this:
app.controller('MyController', function ($scope,$q,MyService) {
$scope.fetch_my_data = function(){
// MyService.load_my_data_service() will return a promise.
$scope.return_my_data_here = MyService.load_my_data_service();
// Use .then() to do something with that promise.
// NOTE: This code will run asynchronously.
$scope.return_my_data_here.then(function(data){
$scope.actualData = data;
console.log($scope.actualData);
});
}
$scope.fetch_my_data() //Initiate on page load
});
I believe you are missing a return statement just before $http({..
return {
load_my_data_service: function(){
return $http({
method: 'GET',
url: 'AJAX PATH',
headers: { "Accept": "application/json;odata=verbose;charset=utf-8"}
}).then(function(result){
return result.data; //to make it cleaner, just return the promise itself to your controller..
});
}
}
This will resolve your service problems. And then in your controller, use
$scope.return_my_data_here = {};
MyService.load_my_data_service().then(function(data){
var My_Stored_Data = data;
My_Stored_Data.data_result_1 = My_Stored_Data.data_result_1.split("\r\n");
My_Stored_Data.data_result_2 = My_Stored_Data.data_result_2.split("\r\n");
$scope.return_my_data_here = My_Stored_Data;
});
I'm trying to set a variable as the data object returned from a http request in angular, but the variable never sets to even if it is in the $scope unless it is nested within the success function. For example, if I do this in the controller :
$scope.hello = [];
var getAppointmentsurl = './dbscripts/getAppointments.php';
$http({method: 'GET', url: getAppointmentsurl}).success(function(data) {
$scope.hello = data;
});
console.log($scope.hello);
}
Hello is blank... so I set it up in services.js like this :
this.getCalendarData=function(){
var hello = [];
var getAppointmentsurl = './dbscripts/getAppointments.php';
$http({method: 'GET', url: getAppointmentsurl}).success(function(data) {
hello = data;
});
return hello;
}
but still hello is blank. Am I missing something obvious?
edit --
this.getCalendarData=function(){
var getAppointmentsurl = './dbscripts/getAppointments.php';
return $http({method: 'GET', url: getAppointmentsurl}).success(function(data) {
return data;
});
}
This is asynchronus call we have to return data like above.
To elaborate on Akash's correct answer, here's an example of how it should work.
In your view you should add logic to show the data only when hello exists. i.e. ng-if="hello"
controller:
ServiceName.getCalendarData().then(function(response) {
$scope.hello = response;
});
service:
this.getCalendarData = function() {
return $http.get('path/to/response/').success(function(data) {
return data;
});
}
As you put the api call as a method in the service, returning data from the service wont resolve yet, So in the controller the service return will only be a promise
serviceName.getCalendarData().then(function(data){
//Success data
},function(){});
Service code must return like the below code and here you will get the entire response object,
return $http({method: 'GET', url:getAppointmentsurl});
One other way to get the data directly resolved stripping of the other properties is returning from service like this,
return $http({method: 'GET', url:getAppointmentsurl}).success(function(data){
return data;
});
I want to create an autocomplete with Angular and since this is my first contact with angular, I`m pretty stucked.
Here is my code:
MenuService.getAutocompleteData(term).then(function (response) {
$scope.menuData = response.data;
});
This is how I call a service that is making the following http call:
return $http({
url : autocompletePath,
method : "POST",
data : {
term: term
}
}).success(function (response) {
return response;
});
The problem is that it seems that is syncronously and my browser freezes when I type fast letters. I saw that it is about that ".then" promise, but I`m not sure how to fix it. Any help would be appreciated.
You do a HTTP-request, which is correct, but you try to return the result on success. Instead you should try to do what needs to be done in your success-handler.
So in your service you would do something like this:
return $http({
url : autocompletePath,
method : "POST",
data : {
term: term
}
}); //note that there is no success handler in your service, because what's supposed to happen when the request completes, is the controller's business, not the service's. The service should only know where to get the data
And you would change your controller to this:
MenuService.getAutocompleteData(term).success(function (response) {
$scope.menuData = response.data;
}); //note the success-handler
Why dont you give this a try?
https://angular-ui.github.io/bootstrap/#/typeahead
I currently have an AJAX call out to a PHP file that works, that is the following:
//Load map from database
function getMap(){
return $.ajax({
url: "getMap.php",
type: "POST",
dataType: 'JSON',
});
};
getMap().done(function(r) {
if (r) {
loadedMap(JSON.parse(r.mapArray), JSON.parse(r.mapProperties)); //call loadedMap(r) if loading a map from DB
} else {
console.log("No data");
}
}).fail(function(x) {
console.log("error");
});
That works within a single javascript file that successfully passes r.mapArray and r.mapProperties to my main loadedMap function.
I'm trying to learn about the IIFE Javascript Module model, and split my work up into separate files.
So, I currently have main.js:
(function() {
// let's get our map
var gameMap = mapGen.getMap().done();
console.log(gameMap);
})();
and mapGen.js:
var mapGen = function() {
return {
getMap: function() {
return $.ajax({
url: "getMap.php",
type: "POST",
dataType: 'JSON',
});
}
};
}()
If I console.log(gameMap), I see the responseText JSON object with my data. I just can't seem to access it. console.log(gameMap.responseText) is undefined. as is gameMap.responseJSON (though I see both of them in the console).
Looking the code over it looks as the the separation of the files was not the issue and that looks to be implemented correctly. The issue is with how you are handling the AJAX request. The function mapGen.getMap() actually returns a jqXHR Object as opposed to the response that you are trying to access.
Just as you had in your previous file, you will need handle the response of your request.
(function() {
// let's get our map request
var gameMap = mapGen.getMap();
gameMap.done(function(r){ ... }).
fail(function(x){ ... });
})();
You will be able to access the response data you are looking for within the done() function.