I've tried other answers with the same problem, but none of them worked. I have the issue where I'm calling my factory and I get the undefined return.
Controller (main.js):
app.controller('MainCtrl', ['$scope','beamAPI', function($scope, beamAPI){
$scope.debug = 'Debug True';
$scope.beamFollowers = 1;
console.log(beamAPI('amtraxtge'));
}]);
Factory (beam.js):
app.factory('beamAPI', function($http) {
var APIuser = {};
APIuser = function(user) {
$http.get('https://beam.pro/api/v1/channels/' + user).
then(function(res){
console.log(res.data);
return res.data;
});
}
return APIuser;
});
Console:
undefined main.js:4
► Object beam.js:6
Your APIuser() doesn't return anything. You need to return the promise and in controller wait for promise to resolve before assigning or logging any of the data
In factory
APIuser = function(user) {
// return $http promise
return $http.get('https://beam.pro/api/v1/channels/' + user).
then(function(res){
console.log('Factory log',res.data);
return res.data;
});
}
In controller
beamAPI('amtraxtge').then(function(data){
$scope.someProperty = data;
console.log('Controller log',data);
});
Related
I have two http requests.
1. post method
2. get method.
I need to get data from two http request.
I added my code. But i think this is not correct approach. Please suggest me.
Question 1:
After two call to synchronous.
Controller
(function() {
'use strict';
angular.module('myApp').controller('loginController', loginController);
loginController.$inject = ['$auth', '$http', '$location', '$scope', '$window', '$rootScope', 'commonService', '$q', '$localStorage'];
// inject an auth service here!
function loginController($auth, $http, $location, $scope, $window, $rootScope, commonService, $q, $localStorage) {
commonService.getHostDetails().then(function(data) {
commonService.login().then(function(data) {
}).catch(function(data) {
alert('Sorry ! test function faild');
});
}).catch(function(data) {
alert('Sorry ! login function faild');
});
};
})();
Service Code:
angular.module('myApp').factory('commonService', ['$q', '$timeout', '$http',
function($q, $timeout, $http, commonService) {
return ( {
login : login,
test : test,
});
function login() {
// create a new instance of deferred
var deferred = $q.defer();
$http.get('host.json')
// handle success
.success(function(data, status) {
deferred.resolve(data);
})
// handle error
.error(function(data) {
deferred.reject(data);
});
// return promise object
return deferred.promise;
}
function test(formData) {
// create a new instance of deferred
var deferred = $q.defer();
console.log("in service");
console.log(formData);
$http.post('/api/test', formData, {
headers : {
'Content-Type' : 'application/json'
}
})
// handle success
.success(function(data) {
deferred.resolve(data);
})
// handle error
.error(function(data) {
deferred.reject(data);
});
// return promise object
return deferred.promise;
}
}]);
Question -2.
Also please suggestme two http request depends on two api.
First http request data need to parse into second api.
Promises are a great way of chaining you calls.
$http.post("your api").then(function(response) {
//do something
return response.data;
}).then(function(data) {
return $http.get("you other api")
}).then(response_from_second_api) {
});
If you have two calls then need to be resolved before you can do anything you could do something like that
var promise1 = $http.get("");
var promise2 = $http.get("");
$q.all([promise1,promise2]).then(values) {
var value_of_promise1 = values[0];
var value_of_promose2 = values[1];
});
I am calling my data from my api through a factory that looks like this:
app.factory('Service', ['$http', function ($http) {
var urlBase = 'http://localhost:50476/api';
var Service = {};
Service.getComp = function () {
return $http.get(urlBase + '/complaints')
};
return Service;
}]);
Then I use my controller to use the directive:
getComp();
$scope.comp = [];
function getComp() {
var deferred = $q.defer();
Service.getComp()
.success(function (comp) {
console.log('comp', comp); //returns array data
$scope.comp = comp.data;
deferred.resolve(comp);
})
.error(function (error) {
$scope.error = 'error' + error.message;
});
return deferred.promise;
}
$scope.index = 0;
$scope.complaints = $scope.comp[0];
console.log($scope.complaints); //undefined
console.log($scope.comp); //array of 0
When I try to access the items outside of the function it is undefined. I tried to look for resolutions like using $q but it is still not displaying data. When I added the deferred part my ng-repeat stops working as well.
Try this:
getComp();
$scope.comp = [];
function getComp() {
return Service.getComp()
.success(function (comp) {
$scope.comp = comp.data;
$scope.complaints = $scope.comp[0];
})
.error(function (error) {
$scope.error = 'error' + error.message;
});
}
The values are undefined when you do your logs because those lines run before your request comes back from the server. That's why setting $scope.complaints has to go into the success callback.
if you want to make sure complaints are loaded on certain states before you start your logic you can use ui-routers resolve keyword (i suppose you are using ui-router with ionic - standard package)
In you main.js
$stateProvider.state('yourState', {
resolve: {
complaints: function(Service) {
return Service.getComp();
}
}
});
in your controller you can then inject complaints
.controller('myController', function(complaints) {
$scope.complaints = complaints;
})
resolve at $stateProvider will block and wait for the promise to resolve...
I have the following controller:
public class UserController : BaseApiController
{
// GET api/<controller>
public string Get()
{
var currentuser = CurrentUser.Name;
return currentuser;
}
}
The value of currentuser I pass it the datacontext in this way:
function getName() {
var deferred = $q.defer();
var promise = deferred.promise;
cachedPromises.currentuser = promise;
$http.get(baseUrl + 'api/user').success(getSucceeded).error(getFailed);
return cachedPromises.currentuser;
function getSucceeded(data) {
console.log('data:', data);
}
function getFailed(parameters) {
console.log("failed", parameters);
}
}
On the console log console.log('data:', data); I get the value and in order to apply binding I have to pass this value to the scope in the controller.js. In order to do that, I have done a controller in this way.
LogName.$inject = ['$scope', 'datacontext']
function LogName($scope, datacontext) {
$scope.name =[];
datacontext.getName().then(function (currentuser) {
$scope.name = currentuser;
});
}
And on the view I have the following code for data binding :
<h1 ng-controller="LogName" class="title">{{name}}</h1>
The binding is shown as an empty array, and I don't understand what goes wrong .
EDIT:
When I do a console log on the controller:
datacontext.getName().then(function (currentuser) {
$scope.name = currentuser;
console.log('current', currentuser);
});
Nothing appears on the view, the compiler does not reach the datacontext.getName
You MVC controller returning string public string Get() and you declare $scope.name =[]; as array change it to $scope.name =''; that should helps
and change your function getName to :
function getName() {
var deferred = $q.defer();
$http.get(baseUrl + 'api/user').success(getSucceeded).error(getFailed);
return deffered.promise;
function getSucceeded(data) {
console.log('data:', data);
//add this
deferred.resolve(data);
}
function getFailed(parameters) {
console.log("failed", parameters);
deferred.reject(parameters);;
}
return deffered.promise;
}
You are never resolving your promise to provide the name. Add a resolve to the getSucceeded function and a reject to the error function.
function getSucceeded(data) {
console.log('data:', data);
promise.resolve(data);
}
function getFailed(parameters) {
console.log("failed", parameters);
promise.reject(parameters);
}
This will provide the data to the functions that are waiting on the promise results.
There are two issues:
Firstly, you are not resolving the promise. You need to resolve your promise with your data that is returned from the server.
Second, the result is actually in the results property of the data that is returned from the server. Here as you are retrieving only name, you should use below code:
function getSucceeded(data) {
console.log('data:', data);
deferred.resolve(data.results[0]);
}
Trying to create a protractor test for my angular app, this is the service I am trying to call from my Jasmine script:
var app =angular.module('app',[]);
app.factory('myService', function($http) {
var myService = {
async: function() {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get('test.json').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
// Return the promise to the controller
return promise;
}
};
return myService;
});
;
My spec is defined like this:
it('should call api i the site', function () {
browser.executeAsyncScript(function(callback) {
var callback = arguments[arguments.length - 1];
var myService = angular.injector(['ng']).get('myService');
myService.async().then(function (d) {
$scope.data = d;
});
callback(null, true);
});
})
When I run the script the line that contains angular.injector(['ng']).get('myService') results in this error:
UnknownError: javascript error: [$injector:unpr] Unknown provider: myServiceProvider <- myService
What is the right injector statement?
try this one,
var injector = angular.injector(['app', 'ng']);
var myService = injector.get('myService');
i have a factory am passing it to controller LoginCtrl
.factory('Fbdata', function(){
var service = {
data: {
apiData: []
},
login: function () {
facebookConnectPlugin.login(["email"],
function() {
facebookConnectPlugin.api("me/?fields=id,email,name,picture", ["public_info","user_birthday"],
function (results) {
service.data.apiData = results;
console.log(service.data.apiData);
return results;
},
function (error) {
console.error('FB:API', error);
});
},
function(err) {
console.error('FB:Login', err);
});
}
};
return service;
})
LoginCtrl:
.controller('LoginCtrl', function($scope, Fbdata){
$scope.login = function(){
if (!window.cordova) {
var appId = "appId";
facebookConnectPlugin.browserInit(appId);
}
$scope.loginData = Fbdata.login();
console.log(Fbdata.data.apiData);
// got empty array []
$scope.retVal= angular.copy(Fbdata.data.apiData);
};
})
the Fbdata.data.apiData return empty array and i only could see the returned data from the login success function in the console .
my template which is has LoginCtrl as controller:
<div class="event listening button" ng-click="login();">Login with Facebook</div>
<h2>{{loginData.name}}</h2>
<h2>{{retVal.name}}</h2>
There is a variety of ways to achieve this, example:
Now I have never used Cordova Facebook Plugin so I'm not sure if you need to run the api function after the log in, or how those procedures need to be ordered. But I wanted to show you an example of how to retrieve the data from the factory using your code sample. Hope that helps
Edit 2:
I have changed my code to using promises that way we make sure that we don't call one without the other being completed, I am not a fan of chaining the login and api functions within one function since it is possible(?) that you may need to call login() but don't want to call api(), please try my code and paste in your console logs in the bottom of your question.
Factory:
// Let's add promises to our factory using AngularJS $q
.factory('Fbdata', ['$q', function($q){
// You could also just replace `var service =` with `return` but I thought this
// would make it easier to understand whats going on here.
var service = {
// I generally nest result to keep it clean when I log
// So results from functions that retrieve results are stored here
data: {
login: [],
api: []
},
api: function() {
var q = $q.defer();
facebookConnectPlugin.api("me/?fields=id,email,name,picture", ["public_info","user_birthday"],
function (results) {
// assign to the object being returned
service.data.api = results;
// The data has returned successfully so we will resolve our promise
q.resolve(results);
},
function (error) {
// We reject here so we can inform the user within through the error/reject callback
q.reject(error);
console.error('FB:API', error);
});
// Now that we have either resolved or rejected based on what we received
// we will return the promise
return q.promise;
},
login: function () {
var q = $q.defer();
facebookConnectPlugin.login(["email"], function (results) {
// assign to the object being returned
service.data.login = results;
q.resolve(results);
}, function(err) {
q.reject(error);
console.error('FB:Login', err);
});
return q.promise;
}
};
return service;
}])
Controller:
.controller('LoginCtrl', function($scope, Fbdata){
$scope.login = function(){
if (!window.cordova) {
var appId = "appid";
facebookConnectPlugin.browserInit(appId);
}
// By using the promises in our factory be can ensure that API is called after
// login by doing the following
// then(success, reject) function allows us to say once we have a return, do this.
Fbdata.login().then(function () {
$scope.loginData = Fbdata.data.login;
// Check what was returned
console.log('loginData', $scope.loginData);
Fbdata.api().then(function () {
$scope.apiData = Fbdata.data.api;
console.log('apiData', $scope.apiData);
}, function () {
// Tell the user that the api failed, if necessary
});
}, function () {
// Tell the user that the log in failed
});
};
});