Factory using $resource return undefined object - angularjs

I have a factory using $resource but cant use object generated as undefined
I've seen so many reponses regarding that problem that i am more and more confusing
here is my factory
angular.module('contrats')
.factory('Contrats', ['$resource',
function($resource) {
return $resource('contrats/:contratId', { contratId: '#_id'}, {
update: {method: 'PUT'},
});
}
]);
here is my controler
// Contrats controller
var app = angular.module('contrats')
.controller ('ContratsController',
['$scope' , '$stateParams', '$location', 'Authentication', 'Contrats', function($scope, $stateParams, $location, Authentication, Contrats)
{
$scope.contrats = Contrats.query();
$scope.nbctrt = $scope.contrats.length;
})];
$scope.contrats.length = > generate error can't get property of undefined
I'stuck for days with that and dont understand Thanks for your advices to a newbie

To clarify my comment.
Add you logs inside the success function, so that the query is complete before logging, something like this
$scope.contrats = Contrats.query(function(success) {
// response from query
console.log(success);
// length of $scope.contrats
console.log('nb contrats',$scope.contrats.length);
// first item in $scope.contrats
console.log('contrats[0]:' , $scope.contrats[0]);
}, function(error){
console.log(error);
});

Related

Promise not resolved correctly when routing

So basically I am using resolve in $routeProvider in order to get my current user's information before I instantiate the controller.
This is how I do it:
userMan.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/userManagement', {
templateUrl: 'userManagement/userManagement.html',
controller: 'userManCtrl',
resolve: {
myUser:function($http){
console.log("I am about to make the call");
$http.get("/irods-cloud-backend/searchByMetadata/getCurrentUser").then( function( result ) {
console.log(result.data);
return result.data;
},
function( result ) {
alert("Unable to find any users! Please try again...");
})
}
}
});
}]);
My controller also looks something like this:
userMan.controller('userManCtrl', ['$scope', '$log', '$http', '$location', 'myUser',
function($scope, $log, $http, $location, myUser){
var currUser = myUser;
Basically my error is that currUser is undefined. This prevents me to check the user's permissions and such.
I have also used:
$scope.$on('$routeChangeSuccess',function(event, current){
alert("loaded!!");
});
To see when this promise is resolved, but I see the alert message as soon as I load into the tab.
I then tried to use a dummy return object simply like
return { someAttr: 'val'};
This functions just fine.. I know its not a promise but did that for sanity purposes..
Any clues for the error?
You don't return from the myUser method, so there's nothing to wait for but undefined. As #JoelCDoyle commented:
Your resolve method must return a promise. $http method returns a promise.
resolve: {
myUser:function($http){
// return here!
return $http.get("/irods-cloud-backend/searchByMetadata/getCurrentUser").then( function( result ) {
console.log(result.data);
return result.data;
}
After feedback from #JoelCDoyle and #baao, I used a different approach.
I simply created a service that handled the GET request and used that in my resolve.
More on this can be viewed here

injecting service into controller not working

Am new to angularjs. I am trying to use angular service to post data but its throwing below error
angular.js:12520 Error: [$injector:unpr] Unknown provider: frontendServiceddProvider <- frontendServicedd <- CustSignupCtrl
service.js
app.service('frontendService', function frontendService ($http, $q, $rootScope){
var list = this;
list.registerCust = function(data){
var defer = $q.defer();
$http({
url: $rootScope.endPoint,
method: "POST",
data: data
})
.success(function(res){
console.log("Successfull!");
defer.resolve(res);
})
.error(function(err, status){
console.log("Failed !");
})
return defer.promise;
}
return list;
});
customer_signup.js
app.controller('CustSignupCtrl', ['$scope', '$filter','frontendService', '$http', 'editableOptions', 'editableThemes','notify','notification','$appConstants',
function('$scope', '$filter','frontendService', '$http','editableOptions', 'editableThemes','notify','notification','$appConstants'){
$scope.pw1 = '';
$scope.registerCustomer = function (data) {
return frontendService.registerCust(data)
}
$scope.signupcustomer = function(){
var payload= {
first_name: $scope.custForm.fname,
last_name: $scope.custForm.lname,
phone: $scope.custForm.phone,
email:$scope.custForm.email,
username:$scope.custForm.username,
password:$scope.custForm.pw1,
usertype:3
}
console.log("inside function");
$scope.registerCustomer(payload).then(function(data){
notification.success(data.result);
},function(err){
notification.error("Error: contact system admin");
});
}
}
])
I have given reference of both js files in index.html.. not getting where am doing wrong.. can anyone help
app.controller('CustSignupCtrl', ['$scope', '$filter', 'frontendService', '$http', 'editableOptions', 'editableThemes','notify','notification','$appConstants',
function($scope, $filter, frontendService, $http, editableOptions, editableThemes, notify, notification, $appConstants){
$scope.pw1 = '';
});
Whatever you inject into controller, should be in the same order.
Remove quotes accross the injectables inside function.
This can be a dependency injection mismatch sort of problem
AngularJS injects object into the function as it sees them inside []
For example if you declare a function inside your js file, say like this
var app = angular.module('app',[]);
app.controller('maincntrl',function($scope){
});
var search = function($scope,searchtext,searchfilters,searchareas)
{
return 'result'
}
console.log(angular.injector.annotate(search));
The result you shall get in your console will be
["$scope","searchtext","searchfilters","searchareas"]
AngularJS parses the function parameters as an array
It goes through each array elements and the moment it sees "$scope", it injects scope object into that position
Now the syntax which you have used is basically used for minification
So according to your declaration
app.controller('CustSignupCtrl', ['$scope','frontendService', '$filter','frontendService', '$http', 'editableOptions', 'editableThemes','notify','notification','$appConstants',
function('$scope', '$filter','frontendService', '$http','editableOptions', 'editableThemes','notify','notification','$appConstants'){
});
So
$scope--> shall be injected into $scope
frontendService-->shall be injected into $filter
$filter--> shall be injected into frontendService
.
.
.
so on
Also the errors(which you mentioned in comments) are occurring because you have declared function parameters as strings in which case the dependency injection is not happening. Fixing these things shall solve your problem

AngularJS factory return no data first time, but after called interval method it does

Im trying to make a AngularJS factory that provides my app with a list of businesses. But i cant seem to get the variable the first time this is run. But after interval is run, i get the variable.
I get this on the first run on the controller in the page:
angular.js:12783 Error: [$injector:undef] Provider 'businessList' must return a value from $get factory method
But I think my solution is faulty, any how? Can anyone point me in the right direction here? For example is using rootScope here a good idea?
What I want is a globally accessible list of businesses in my app, that is collected on start of visit, and updates itself with a timer. So i dont have to all the time call for induvidial requests from the laravel backend, when i can just find it in that list.. is my idea.
Factory:
myApp.factory('businessList', ['$interval', '$http', '$rootScope',
function($interval, $http, $rootScope) {
function bedriftliste() {
$http.get('get/allebedrifter')
.then(function(result) {
bedrifter = result.data;
$rootScope.bedrifter = bedrifter;
});
return $rootScope.bedrifter;
}
var bedrifter = bedriftliste();
// start periodic checking
$interval(bedriftliste, 5000);
return bedrifter;
}
]);
Controller
myApp.controller('bsC', ['$rootScope', '$scope', 'businessList',
function($rootScope, $scope, businessList) {
$scope.allebedrifter = businessList;
}]);`
I solved this by just doing a http.get if object was null.
if (!$rootScope.allebedrifter) {
$http.get('get/bedrift/' + $scope.tslug)
.then(function(result) {
bedriften = result.data;
$scope.bedriften = bedriften;
});
Seems to work fine like this
Although I am late in pointing out but that doesn't seem to be a proper solution to this problem. You need to make these changes in factory:
myApp.factory('businessList', ['$interval', '$http', '$rootScope',
function($interval, $http, $rootScope) {
function bedriftliste() {
return $http.get('get/allebedrifter');
}
}
]);
and in the controller you'll do something like this:
myApp.controller('bsC', ['$rootScope', '$scope', 'businessList', function($rootScope, $scope, businessList) {
function TestFunction(){
businessList.bedriftliste().then(function successCallback(response) {
$scope.allebedrifter = response.data;
//it will invoke 5 seconds after you receive the response from your factory method, I didn't test it but it will solve your problem
$interval(TestFunction, 5000);
}, function errorCallback(response) {
});
}
}]);

AngularJS - Factory - TypeError: Cannot read property 'getSpec' of undefined

I am starting with AngularJS and i am having some issues when trying to use a factory from a controller.
I have the following factory
angular.module('testingApp')
.factory('factoryService', function ($http) {
// Service logic
var getSpec = function(p) {
return $http.get('http://someurl//?p=' + p);
};
return {
getSpec: getSpec
};
});
and then i try to consume it from the controller as follows
angular.module('testingApp')
.controller('ServiceincientsCtrl',[ function (factoryService,$scope) {
console.log('Starting Service Incident Controller');
factoryService.getSpec('AAA').then(function(response){
$scope.result = response.data;
}, function(error){
console.log('opsssss' + error);
});
}]);
But when i try to run it i receive the following message
TypeError: Cannot read property 'getSpec' of undefined
I don't know what i am missing,It should be a newbbie error, I googled it and i tried many examples with the same result.
Any ideas of what i am doing wrong?
Thanks!
Looks like you are not using the dependancy array notation properly. Please refer the below code. Please add 'factoryService' & '$scope' as array items.
.controller('ServiceincientsCtrl', ['factoryService', '$scope', function(factoryService, $scope) {
console.log('Starting Service Incident Controller');
factoryService.getSpec('AAA').then(function(response) {
$scope.result = response.data;
}, function(error) {
console.log('opsssss' + error);
});
}]);
Angular documentaion on dependancy injection.
First of all, you didn't declare your controller properly. It should look like this:
.controller('ServiceincientsCtrl',['$scope', 'factoryService', function($scope, factoryService) {
I personally use Services as I find them more readable.
Here's what your factory would look like as a Service:
myApp.service('factoryService', function ($http) {
this.getSpec = function(p) {
return $http.get('http://someurl//?p=' + p);
}
});
This would work with your current controller.

Problems using $http inside a Service

I have a basic data Service which will be used across Controllers. But I'm having an issue grabbing some data that's been added via $http.
Service:
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
$http.get('/json').success(function(resp){
_this.dropdownData.industries = resp.industries;
});
}]);
Controller:
angular.module('core').controller('SignupController', ['$scope', '$http', '$state', 'FormService', function($scope, $http, $state, FormService) {
console.log(FormService.dropdownData); // Shows full object incl industries
console.log(FormService.dropdownData.industries); // empty object {}
}]);
How do I get FormService.dropdownData.industries in my controller?
Create a service like below
appService.factory('Service', function ($http) {
return {
getIndustries: function () {
return $http.get('/json').then(function (response) {
return response.data;
});
}
}
});
Call in controller
appCtrl.controller('personalMsgCtrl', ['$scope', 'Service', function ($scope, Service) {
$scope.Industries = Service.getIndustries();
}]);
Hope this will help
Add a method to your service and use $Http.get inside that like below
_this.getindustries = function (callback) {
return $http.get('/json').success(function(resp){
_this.dropdownData.industries = resp.industries;
callback(_this.dropdownData)
});
};
In your controller need to access it like below.
angular.module('core').controller('myController', ['$scope', 'FormService', function ($scope, FormService) {
FormService.getDropdownData(function (dropdownData) {
console.log(dropdownData); // Shows full object incl industries
console.log(dropdownData.industries); // object {}
});
} ]);
Given that your console log shows the correct object, that shows your service is functioning properly. Only one small mistake you have made here. You need to access the data attributes in your return promise.
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
$http.get('/json').success(function(resp){
//note that this is resp.data.industries, NOT resp.industries
_this.dropdownData.industries = resp.data.industries;
});
}]);
Assuming that you're data is indeed existing and there are no problems with the server, there are quite a few possible solutions
Returning a promise
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
_this.dropdownData.industries = $http.get('/json');
}]);
//Controller
FormService.industries
.then(function(res){
$scope.industries = res.industries
});
Resolving with routeProvider / ui-route
See: $http request before AngularJS app initialises?
You could also write a function to initialize the service when the application starts running. At the end of the day, it is about waiting for the data to be loaded by using a promise. If you never heard about promises before, inform yourself first.
The industries object will be populated at a later point in time when the $http call returns. In the meantime you can still bind to the reference in your view because you've preserved the reference using angular.copy. When the $http call returns, the view will automatically be updated.
It is also a good idea to allow users of your service to handle the event when the $http call returns. You can do this by saving the $promise object as a property of industries:
angular.module('core').service('FormService', ['$http', function($http) {
var _this = this;
_this.dropdownData = {
contactTimes: ['Anytime','Morning','Afternoon','Evening'],
industries: {},
};
_this.dropdownData.industries.$promise = $http.get('/json').then(function(resp){
// when the ansyc call returns, populate the object,
// but preserve the reference
angular.copy( resp.data.industries, _this.dropdownData.industries);
return _this.dropdownData.industries;
});
}]);
Controller
app.controller('ctrl', function($scope, FormService){
// you can bind this to the view, even though the $http call has not returned yet
// the view will update automatically since the reference was preserved
$scope.dropdownData = FormService.dropdownData;
// alternatively, you can hook into the $http call back through the $promise
FormService.dropdownData.industries.$promise.success(function(industries) {
console.log(industries);
});
});

Resources