I have a factory that returns an object from $http.get
app.factory( 'myFactory', function($http) {
return {
get: function() {
return $http.get('/data').success(function(data) {
return data
})
}
}
})
then
$scope.listings = myFactory.get()
In index.html, I use ng-repeat on listings.data and there is no problem finding each object.
Then from a directive I call .getListings() that's in my controller and in the Chrome Javascript console $scope.listings =
Object {then: function, success: function, error: function, $$v: Object}
Why can't I just use this?
$scope.listings.data
And is it ok to use this?
$scope.listings.$$v.data
What is $$v?
You are making little mistake in your code with get in service you return a promise object which will be filled when you sucessfully complete response from the server so kindly modify your code below to make it working.
app.factory( 'myFactory', function($http) {
return {
get: function() {
return $http.get('/data')
}
}
})
myFactory.get().then(function(data){
$scope.listings=data;
});
Related
Hi I have small factory (myFactory) in my application:
.factory('myFactory', ['$q', function ($q) {
function myMethod() {
.....
}
return {
myMethod: myMethod
};
}]);
I want to get access to myFactory.myMethod() in protractor test so in onPrepare() I'm using
browser.executeScript(function() {
return angular.element(document).injector().get('myFactory');
}).then(function (myFactory) {
console.log('myFactory: ', myFactory);
myFactory.myMethod();
});
for console.log('myFactory: ', myFactory) I see I get object:
myFactory: {
myMethod: {}
}
Then for myFactory.myMethod(); I see error:
TypeError: object is not a function
Anyone know how I can get access to factory from protractor to be able to execute method?
I use services to access user information in my app via Protractor, I went ahead and played around with this as close to your code as I could, my comment above should be your solution. Here's the longer explanation:
So we have a service Users, with a function called getCurrent() that will retrieve the information of the current user. So first time I tried code similar to yours:
browser.executeScript(function () {
return angular.element(document.body).injector().get('Users');
}).then(function (service) {
console.log(service); // logs object which has getCurrent() inside
service.getCurrent(); // error, getCurrent() is not a function
});
This logged the Users object, and included the function getCurrent(), but I encountered the same error as you when I tried to chain the call service.getCurrent().
What DID work for me, was simply moving the .getCurrent() into the execute script. i.e.
browser.executeScript(function () {
return angular.element(document.body).injector().get('Users').getCurrent();
}).then(function (service) {
console.log(service); // logs John Doe, john.doe#email.com etc.
});
So applying that to your case, the below code should work:
browser.executeScript(function() {
return angular.element(document).injector().get('myFactory').myMethod();
}).then(function (myFactory) {
console.log(myFactory); // this should be your token
});
And just a minor FYI, for what it's worth you also could have written this code by passing in a string to executeScript:
browser.executeScript('return angular.element(document).injector().get("myFactory").myMethod()').then(function (val) {
console.log(val);
});
I am using 2 service in controller
First Service is to get AjaxResponse where logic to fetching the response is mentioned
The second Service calls the first service to make Http request and get result and then, in turn, return it to the controller
Ctrl Dependency injected firstService,secondService
this.getService = secondService.getData(param);
First Service--> firstService
this.httpResponse(param){
var re = $http.get(param);
return re.then(success,fail);
}
function success(data){
return data;
}
function fail(data){
console.log(data);
}
Second Service (Dependency injection of First Service)
function secondService(firstService){
this.getData = function(param){
return firstService.httpResponse(param);
};
}
this.getService is coming as undefined, all the call are going properly.
Even tried the following code:
secondService.getData(param).then(function(data){console.log(data);});
That doesn't help either.
You should chain the promises in these kinds of situations.
First, you define your service. It should contain two distinct functions. As an example, I did a GET and a POST.
angular.module("myApp",[]).factory("SharedServices", function($http) {
return {
getItem: function() {
return $http.get('path/to/api');
},
postItem: function(payload) {
return $http.post('path/to/api', payload);
}
};
});
Then, reference the service in your controller. getItem() will return a promise, where you can use it using .then to call your second service in the success callback.
angular.module("myApp",[]).controller("MainCtrl", function($scope, SharedServices) {
SharedServices.getItem().then(function(response) {
//success, got something
//call the second part
var payload = { myPayload: response.data.someItem };
SharedServices.postItem(payload).then(function(response) {
//success
}, function(response) {
//an error has occurred to the second call--POST
});
}, function(response) {
//an error occurred to the first call--GET
});
});
Used Callback to get the result.It is similar to deferred(promise)
I am trying to load JSON data from an external file using a service in AngularJS.
myApp.service('ContactsListService', function($http) {
var contactsList = $http.get('js/contacts.json').success(function(data){
return data;
});
console.log(contactsList); // prints some $http object
return {
'contactsList': contactsList;
};
}
myApp.controller('ContactDisplayController',['$scope','ContactsListService',function($scope, ContactsListService){
$scope.contacts = ContactsListService.contactsList;
console.log(ContactsListService.contactsList); // prints 'undefined' here
}]);
**JSON file:**
[
{
name: 'Steph Curry',
mobile: '111111111'
},
{
name: 'Lebron James',
mobile: '2323232323'
}
]
I want to use the data from the service in the controller, I am unable pass that data. Correct me if I am injecting the service in an incorrect way.
Thanks!
You are storing the $http promise rather than the response from that ajax call. A better approach would be for the service to define a method that returned the promise, and for your controller to get that promise and use the result.
myApp.service('ContactsListService', function($http) {
this.getContactsList = function() {
return $http.get('js/contacts.json');
};
});
myApp.controller('ContactDisplayController',['$scope','ContactsListService',function($scope, ContactsListService){
ContactsListService.getContactsList().success(function(data) {
$scope.contacts = data;
});
}]);
Thanks for the answer Joey, I have tried in your way, I am unable to print data outside the success function:
myApp.controller('ContactDisplayController',['$scope','ContactsListService',function($scope, ContactsListService){
ContactsListService.getContactsList().success(function(data) {
$scope.contacts = data;
console.log($scope.contacts); // prints data here.
});
console.log($scope.contacts); // prints undefined here.
}]);
Just need to know how this is flowing. Get the data, then do something with it, right there in the handling of that data.
myApp.controller('ContactDisplayController',['$scope','ContactsListService',function($scope, ContactsListService){
$scope.contacts = []; //initialize it
ContactsListService.getContactsList().success(function(data) {
$scope.contacts = data;
//now do stuff with it
});
//console logging here happens before your async call returns
}]);
So to summarise I am using angular-ui router resolve function to retrieve state specific data. However it doesn't seem to full wait for the promise to resolve:
state('parent.ChildState', {
url: '/myUrl?param1¶m1',
templateUrl: 'views/list.view.html',
controller: 'MyController',
resolve: {
data: resolveData
}
}).
function resolveData($stateParams, Utils) {
var filters = Utils.getFilters($stateParams);
DataService.myDataObj = DataService.get(filters, function(result, headers) {
DataService.myDataObj = result;
});
return DataService.myDataObj;
// Note I have also tried returning directly the DataService.get call however this makes all the below console log statements as undefined (see below for the controller code to know what I mean). So I do the assignment first and then return that.
}
Now in the controller I had a function that executes on load like so:
function ExpensesController(DataService) {
$scope.viewData = DataService;
initData();
function initData() {
// this generally logs a ngResource and shows the full data obj on console
console.log($scope.viewData.myDataObj);
// this gets undefined on console
console.log($scope.viewData.myDataObj.someField1);
// this log fine, however why do I need to do promise
// resolve? should be resolved already right?
$scope.viewData.myDataObj.$promise.then(function() {
console.log($scope.viewData.myDataObj.someField1);
});
As your required data to resolve is async, you need to return a promise and add return statement inside your callback function.
function resolveData($stateParams, Utils) {
var filters = Utils.getFilters($stateParams);
return DataService.get(filters, function(result, headers) {
DataService.myDataObj = result;
return DataService.myDataObj
});
}
You can read ui-router resolve docs more about how resolver works and when they should return promise or pure values.
I don;t know if I have got your problem :), but here is what I feel is wrong
1) in the resolve return a promise, it should not be resolved
function resolveData($stateParams, Utils) {
var filters = Utils.getFilters($stateParams);
return DataService.get(filters);
}
2) In the controller you should inject the data that is declared in resolve not the DataService so your controller should be
function ExpensesController(data) {
$scope.viewData = data;
}
I have a problem with outputting the values of a promise function.
$scope.getTeacher = function(teacherAbr) {
var promise = dataService.getTeacher(teacherAbr);
var testje = promise.then(function(payload) {
return payload;
});
return testje; // outputs an d object, not the direct payload values
};
The output of this controller function is this:
However, when I'm doing testje.$$state it returns undefined. How can I output the value object? I can't output the payload variable in a new $scope, because this data is dynamic.
Here is a simplified version of this on Plunker.
You should change the way you think about things when you work with asynchronous code. You no longer return values, instead you use Promise or callback patterns to invoke code when data becomes available.
In your case your factory can be:
.factory('dataService', function($http, $log, $q) {
return {
getTeacher: function(teacher) {
// Originally this was a jsonp request ('/teacher/' + teacher)
return $http.get('http://echo.jsontest.com/key/value/one/two').then(function(response) {
return response.data;
}, function() {
$log.error(msg, code);
})
}
};
});
And usage in controller:
dataService.getTeacher('Lanc').then(function(data) {
$scope.teacher = data;
});
Also $http.get already returns promise, so you don't have to create one more with $q.defer().
Demo: http://plnkr.co/edit/FNYmZg9NJR7GpjgKkWd6?p=preview
UPD
Here is another effort for combining lessons with teachers.
Demo: http://plnkr.co/edit/SXT5QaiZuiQGZe2Z6pb4?p=preview
//in your services file
return {
getTeacher: function (teacher) {
// Originally this was a jsonp request ('/teacher/' + teacher)
return $http.get('http://echo.jsontest.com/key/value/one/two')
})
//change the controller to this
dataService.getTeacher(teacherAbr).then(function(msg){
$scope.getdata=msg.data;
console.log("From server"+msg.data);
});