$scope is undefined inside $http call - javascript

My angular code
angular.module('MyApp').
controller('ProductController', function ($scope, DropDownService) {
$scope.Product = {};
$scope.ProductCategoryList = null;
DropDownService.GetCategory().then(function (d)
{
$scope.ProductCategoryList = d.data;
});
}).
factory('DropDownService', function ($http) {
var fac = {};
fac.GetCategory = function() {
return $http.get('/Product/GetAllCategory');
};
return fac;
});
my server side
public JsonResult GetAllCategory()
{
//List<tblCategory> categories = new List<tblCategory>();
try
{
using(CurtainHomesDBEntities dc = new CurtainHomesDBEntities())
{
var categories = dc.tblCategory.Select(a => new { a.Id, a.CatagoryName }).ToList();
return Json(new { data = categories, success = true }, JsonRequestBehavior.AllowGet);
}
}
catch(Exception ex)
{
return Json(ex);
}
}
I did same way many times. but throwing js error ReferenceError: $scope is not defined when assigning value to $scope.ProductCategoryList after $http request. What is the problem here? I tried many way but couldn't find out.
Even I tried in this way
angular.module('MyApp').
controller('ProductController', function ($scope, $http) {
$scope.Product = {};
$scope.LoadCategory = function () {
$scope.categoryList = null;
$http.get('/Product/GetAllCategory/')
.success(function (data) {
$scope.categoryList = data.data;
})
.error(function (XMLHttpRequest, textStatus, errorThrown) {
toastr.error(XMLHttpRequest + ": " + textStatus + ": " + errorThrown, 'Error!!!');
})
};
});
Same problem. $scope is not defined

You need to inject $scope as well as your service
angularModule.controller("ProductController", ["$scope","$http", 'DropDownService', function ($scope, $http, DropDownService) {
$scope.Product = {};
$scope.ProductCategoryList = null;
DropDownService.GetCategory().then(function (d)
{
$scope.ProductCategoryList = d.data;
});
}]);

Inject the service in your controller,
angularModule.controller("ProductController", ['$scope','$http', 'DropDownService', function ($scope, $http, DropDownService) {
$scope.Product = {};
$scope.ProductCategoryList = null;
DropDownService.GetCategory().then(function (d)
{
$scope.ProductCategoryList = d.data;
});
})

Related

Send data through a POST request from Angular factory

I have this in the controller
angular.module('myApp')
.controller('TaskController', function ($scope, TaskFactory) {
$scope.addTodo = function () {
$scope.todos.push({text : $scope.formTodoText});
$scope.formTodoText = '';
};
});
and this in the factory
angular.module('myApp')
.factory('TaskFactory', function ($q, $http) {
var sendTasks = function(params) {
var defer = $q.defer();
console.log(1, params);
$http.post('http://localhost:3000/task/save', params)
.success(function(data) {
console.log(2);
console.log('data', data);
})
.error(function(err) {
defer.reject(err);
});
return defer.promise;
}
return {
sendTask: function(taskData) {
console.log('taskData', taskData);
return sendTasks('/task/save', {
taskData : taskData
})
}
}
});
all I need is to know, how to send the data from the controller to the factory in order to do the POST to the specified route ?
You just need to call the function/method inside factory with the required params.
angular.module('myApp')
.controller('TaskController', function ($scope, TaskFactory) {
$scope.addTodo = function () {
$scope.todos.push({text : $scope.formTodoText});
TaskFactory.sendTask({data : $scope.formTodoText})
$scope.formTodoText = '';
};
});
You can follow Dan Wahlin blog post.
Controller:
angular.module('customersApp')
.controller('customersController', ['$scope', 'dataFactory', function ($scope, dataFactory) {
$scope.status;
dataFactory.updateCustomer(cust)
.success(function () {
$scope.status = 'Updated Customer! Refreshing customer list.';
})
.error(function (error) {
$scope.status = 'Unable to update customer: ' + error.message;
});
}
Factory:
angular.module('customersApp')
.factory('dataFactory', ['$http', function($http) {
var urlBase = '/api/customers';
dataFactory.updateCustomer = function (cust) {
return $http.put(urlBase + '/' + cust.ID, cust)
};
}
Hope that solve your problem.
You can call the function directly on the TaskFactory that you pass into the controller as a dependency.
I've cleaned up your code a bit and created a plunk for you here:
And here's the code:
Controller
(function(angular) {
// Initialise our app
angular.module('myApp', [])
.controller('TaskController', function($scope, TaskFactory) {
// Initialise our variables
$scope.todos = [];
$scope.formTodoText = '';
$scope.addTodo = function() {
// Add an object to our array with a 'text' property
$scope.todos.push({
text: $scope.formTodoText
});
// Clear the input
$scope.formTodoText = '';
// Call function to send all tasks to our endpoint
$scope.sendTodos = function(){
TaskFactory.sendTasks($scope.todos);
}
};
});
})(angular);
Factory
(function(angular) {
angular.module('myApp')
.factory('TaskFactory', function($q, $http) {
var sendTasks = function(params) {
var defer = $q.defer();
$http.post('http://localhost:3000/task/save', params)
.success(function(data) {
console.log('data: ' + data);
})
.error(function(err) {
defer.reject(err);
});
return defer.promise;
}
return {
sendTasks: sendTasks
}
});
})(angular);

Angular service return undefined

I have a problem with my service in angular.
My service has the next code:
app.service("Utilidades", ['$http', '$window', function ($http, $window) {
return {
Get: function (urlAbsoluta, parametros, callback) {
var Utilidades = this;
$http
.get(app.UrlBase + urlAbsoluta, parametros)
.then(function (data) {
var Datos = angular.fromJson(data);
Utilidades.GuardarToken(Datos.Token);
callback(Datos);
});
},
ObtenerMenu: function () {
var Utilidades = this;
Utilidades.Get("Administracion/Api/Usuarios/Menu", {}, function (Datos) {
Datos = angular.fromJson(Datos.data);
if (Datos.Error == "") {
return Datos.Resultado;
} else {
return "";
}
});
}
}
}]);
Then, in my controller i have the next code:
app.controller('LoginCtrl', ['$scope', '$http', '$location', 'Utilidades',
function Iniciador($scope, $http, $location, Utilidades) {
var Li = this;
Li.Usuario = "";
Li.Contrasena = "";
Li.Error = "";
Li.MenuItems = [];
Li.Menu = function () {
Li. MenuItems = Utilidades.ObtenerMenu();
}
}]
);
When i run this, Li.MenuItems have undefined value and i don't know why.
Your return statements are in a function inside your ObtenerMenu method so the ObtenerMenu method is not actually returning anything. You need to provide a way to access the resulting value:
Service
app.service("Utilidades", ['$http', '$window', function ($http, $window) {
return {
Get: function (urlAbsoluta, parametros) {
var Utilidades = this;
// v------------ return statement here
return $http
.get(app.UrlBase + urlAbsoluta, parametros)
.then(function (data) {
var Datos = angular.fromJson(data);
Utilidades.GuardarToken(Datos.Token);
// v------------ return statement here
return Datos;
});
},
ObtenerMenu: function () {
var Utilidades = this;
// v------------ return statement here
return Utilidades.Get("Administracion/Api/Usuarios/Menu", {})
.then(function (Datos) {
if (Datos.Error == "") {
return Datos.Resultado;
} else {
return "";
}
});
}
};
}]);
In Controller
Li.Menu = function () {
Utilidades.ObtenerMenu()
.then(function (resultado) {
Li. MenuItems = resultado;
});
}
It's because ObtenerMenu function is asynchronous function. This function doesn't return anything initially (so undefined) and later, after some time when ajax request finishes, this function is already finished its execution stack

AngularJS filter table: $http.get

I am using AngularJS to set up a table and filter its data by a search or category keywords. I
AngularJS
categorieFilter = angular.module("categorieFilter", [])
categorieFilter.controller("catFilter", ["$scope", "store", function($scope, store){
$scope.search = "";
$scope.products = [];
$scope.categories = [];
$scope.categories = store.getCategories();
$scope.products = store.getProducts();
$scope.filterProductsByCats = function(category){
$scope.search = category;
};
}])
categorieFilter.factory('store', function($http){
return {
getCategories: $http.get('api/categories').success(function (data) {
return data;
}),
getProducts : $http.get('api/products').success(function (data) {
return data;
}
};
});
The $http.get on its own is working, when I surf directly to my api I get the required data. Also when I do a alert(data) ifter the $hhtp.get in categories, I get the data I need... So this should be working but it doesn't. I get an error:
TypeError: store.getCategories is not a function
And I got no clue where this is coming from. Anybody a solution to this problem?
When using a factory you should do new function to return a constructor:
function myFactoryFunction() {
return function() {
var a = 2;
this.a2 = function() {
return a*2;
};
};
}
---------------------------------------------------------------------------------
// Injected in your controller
var myShinyNewObject = new myInjectedFactory();
$scope.four = myShinyNewObject.a2();
From this detailed post angular.service vs angular.factory
In your case
var storeFactory = new store();
storeFactory.getProducts();
Updated version, with TS code:
categorieFilter = angular.module("categorieFilter", [])
/**
Store factory
*/
categorieFilter.controller("catFilter", ["$scope", "store", function($scope, store){
$scope.search = "";
$scope.products = [];
$scope.categories = [];
store.getCategories().then(function(data){
$scope.categories = data;
})
store.getProducts().then(function(data){
$scope.products = data;
})
$scope.filterProductsByCats = function(category){
$scope.search = category;
};
}])
/**
Store factory
*/
categorieFilter.factory('store', function($http, $q){
function _getCategory (){
var deferred = $q.defer();
$http.get('api/categories').success(function (data) {
deferred.resolve(data);
})
return deferred.promise;
}
function _getProducts (){
var deferred = $q.defer();
$http.get('api/products').success(function (data) {
deferred.resolve(data);
}
return deferred.promise;
}
return {
getCategories: _getCategory,
getProducts : _getProducts
};
});
I usually create services using $resource. You could try this:
categorieFilter = angular.module("categorieFilter", []);
categorieFilter.factory('categoryStore', [
'$resource',
function($resource) {
return $resource('/api/categories/', {}, {
getCategories: { method: 'GET', params: {} },
});
}
]);
categorieFilter.factory('productsStore', [
'$resource',
function ($resource) {
return $resource('/api/products/', {}, {
getProducts: { method: 'GET', params: {} },
});
}
]);
categorieFilter.controller("catFilter", [
"$scope", "categoryStore", "productsStore", function ($scope, categoryStore, productsStore) {
$scope.search = "";
$scope.products = [];
$scope.categories = [];
$scope.categories = categoryStore.getCategories();
$scope.products = productsStore.getProducts();
$scope.filterProductsByCats = function(category) {
$scope.search = category;
};
}
]);
I usually write http factories passing a callback function parameter (I usually work with Node and I'm used to do this for long working functions). Taking your code it will looks something like this:
categorieFilter = angular.module("categorieFilter", [])
categorieFilter.controller("catFilter", ["$scope", "store", function($scope, store){
$scope.search = "";
$scope.products = [];
$scope.categories = [];
store.getCategories(function(err, data){
if(!err)
$scope.categories = data;
});
store.getProducts(function(err, data){
if(!err)
$scope.products = data;
});
$scope.filterProductsByCats = function(category){
$scope.search = category;
};
}])
categorieFilter.factory('store', function($http){
return {
getCategories: function(next){
$http.get('api/categories')
.success(function (data) {
next(null, data);
})
.error(function(headers, status){
next(status, null);
});
},
getProducts : function(next){
$http.get('api/products')
.success(function (data) {
next(null, data);
})
.error(function(headers, status){
next(status, null);
});
}
};
});
As you can see now factory takes a callback that will be called with error and data parameters, so error handling can be delegate or not to the controller. This is pretty useful for complex situations.
Here's a plunker that works using $q and defer explicitly with some random JSON.
var app = angular.module('categorieFilter', []);
app.factory('store', function($http, $q){
return {
getCategories: function() {
var deferred = $q.defer();
$http.get('https://api.myjson.com/bins/2gamd')
.success(deferred.resolve)
.error(deferred.resolve);
return deferred.promise;
}
}
})
.controller('catFilter', function($scope, store){
store.getCategories().then(function(data) {
$scope.categories = data.stories;// change data.stories to whatever your data is
});
});

Angular Factory Not passing data back

I am trying to create an Angular Factory, this is based on a example from a plural site course http://www.pluralsight.com/training/player?author=shawn-wildermuth&name=site-building-m7&mode=live&clip=3&course=site-building-bootstrap-angularjs-ef-azure.
From debugging the code in Chrome it appears to run fine. I can see when I debug it that the service gets my data and puts it in my array but when I look at the controller in either $scope.data or dataService.data the arrays are empty. I don't see any javascript errors. I'm not sure what I'm doing wrong, any suggestions. I'm using AngularJS v1.3.15.
module.factory("dataService", function($http,$routeParams,$q) {
var _data = [];
var _getData = function () {
var deferred = $q.defer();
$http.get("/api/v1/myAPI?mainType=" + $routeParams.mainType + "&subType=" + $routeParams.subType)
.then(function (result) {
angular.copy(result.data,_data);
deferred.resolve();
},
function () {
//Error
deferred.reject();
});
return deferred.promise;
};
return {
data: _data,
getData: _getData
};});
module.controller('dataController', ['$scope', '$http', '$routeParams', 'dataService',function ($scope, $http, $routeParams, dataService) {
$scope.data = dataService;
$scope.dataReturned = true;
$scope.isBusy = true;
dataService.getData().then(function () {
if (dataService.data == 0)
$scope.dataReturned = false;
},
function () {
//Error
alert("could not load data");
})
.then(function () {
$scope.isBusy = false;
})}]);
On
return {
data: _data,
getData: _getData
};});
you have "data: _data," while your array is named just "data". Change the name of the variable to match and it will work:
var _data = [];
Why would you use deferred from $q this way?
The proper way to use $q:
$http.get("/api/v1/myAPI?mainType=" + $routeParams.mainType + "&subType=" + $routeParams.subType)
.success(function (result) {
deferred.resolve(result);
}).error(
function () {
//Error
deferred.reject();
});
And then in controller
dataService
.getData()
.then(function success(result) {
$scope.data = result; //assing retrived data to scope variable
},
function error() {
//Error
alert("could not load data");
});
In fact, there are some errors in your codes :
In your Service, you define var data = [];, but you return data: _data,. So you should correct the defination to var _data = []
you don't define _bling, but you use angular.copy(result.data,_bling);
One more question, why do you assigne the service to $scope.data : $scope.data = dataService ?
EDIT :
Notice that there 3 changes in the following codes:
comment the $scope.data = dataService;, because it makes no sense, and I think that $scope.data should be the data that the service returns.
$scope.data = dataService.data;, as I described in 1st point. You can see the result from the console.
In the if condition, I think that you want to compare the length of the returned data array, but not the data.
module.controller('dataController', ['$scope', '$http', '$routeParams', 'dataService',function ($scope, $http, $routeParams, dataService) {
// $scope.data = dataService;
$scope.dataReturned = true;
$scope.isBusy = true;
dataService.getData().then(function () {
if (dataService.data.length === 0){
$scope.dataReturned = false;
}else{
$scope.data = dataService.data;
console.log($scope.data);
}
},
// other codes...
})}]);

How can I inject multiple services into one controller?

I have an EmailAccountsController and I need to inject 'Hosting' and 'EmailAccount' services into it. Here is my code:
hostingsModule.controller('EmailAccountsCtrl', ['$scope', 'Hosting', 'EmailAccount', function ($scope, Hosting, EmailAccount) {
var hostingId = 1
$scope.hosting = Hosting.find(hostingId);
$scope.emailAccounts = EmailAccount.all(hostingId)
}]);
The error message is TypeError: Cannot call method 'all' of undefined
When I inject only one service into the same controller, everything works. Is there a way how to inject multiple services into one controller?
EDIT: I've tried to put all the relevant code into one file. It' looks like this:
hostingsModule.factory('Hosting', ['$http', function($http) {
var Hosting = function(data) {
angular.extend(this, data);
};
Hosting.all = function() {
return $http.get('<%= api_url %>/hostings.json').then(function(response) {
return response.data;
});
};
Hosting.find = function(id) {
return $http.get('<%= api_url %>/hostings/' + id + '.json').then(function(response) {
return response.data;
});
}
return Hosting;
}]);
hostingsModule.factory('EmailAccount', ['$http', function($http) {
var EmailAccount = function(data) {
angular.extend(this, data);
};
EmailAccount.all = function(hostingId) {
return $http.get('<%= api_url %>/hostings/' + hostingId + '/email-accounts.json').then(function(response) {
return response.data;
});
};
EmailAccount.find = function(id) {
return $http.get('<%= api_url %>/hostings/' + id + '.json').then(function(response) {
return response.data;
});
};
}]);
hostingsModule.controller('EmailAccountsCtrl', ['$scope', 'Hosting', 'EmailAccount', function($scope, Hosting, EmailAccount) {
var hostingId = 1;
$scope.hosting = Hosting.find(hostingId);
$scope.emailAccounts = EmailAccount.all(hostingId)
console.log($scope.hosting);
console.log($scope.emailAccounts);
}]);
Scope issue. You need to return EmailAccount since it is initialized inside the closure.
You need to add return EmailAccount; like what you did for Hosting.
Or try this code:
hostingsModule.factory('EmailAccount', ['$http', function ($http) {
var service = {
all: function (hostingId) {
return $http.get('<%= api_url %>/hostings/' + hostingId + '/email-accounts.json').then(function (response) {
return response.data;
});
},
find: function (id) {
return $http.get('<%= api_url %>/hostings/' + id + '.json').then(function (response) {
return response.data;
});
}
}
return service;
}]);

Categories

Resources