I'm trying to pass a scope to a factory and use it in the controller where the function should be invoked, but it just doesn't work.
var myApp = angular.module('mainApp', []);
myApp.factory("UserService", function ($http) {
var users = ["xxxxx", "yyyyy", "zzzzz"];
return {
all: function () {
return users;
console.log( users );
},
first: function () {
return users[1];
},
checkUser: function(elUrl, classHide, classShow){
$http.post(elUrl)
.success(function (data, status, headers, config) {
if (!data.isMember) {
el = classHide //should be when invoking: $scope.mailexist = classHide;
$('form').submit();
} else {
el = classShow //should be when invoking: $scope.mailexist = classShow;
return false;
}
}).error(function (data, status, header, config) {
//$scope.ResponseDetails = "Data: " + data +
"<hr />status: " + status +
"<hr />headers: " + header +
"<hr />config: " + config;
});
}
};
});
myApp.controller('mainCtrl', ['$scope', '$http', 'UserService', function ($scope, $http, UserService) {
UserService.checkUser( 'inc/memberSearch.jsp?user.Email=' + $scope.umail + '&group.PK=' + angular.element('.grp').val(),
$scope.mailexist,
'mail-exist-hide',
'mail-exist-show');
}]);
mailexists is the ng-class for the text element in the HTML which should be shown or hidden depending on the server response:
<p ng-class="mailexist">Text Text text Text</p>
The function in the controller is being invoked but The Text doesn't appear. If I add the $scope in the factory, then I get $scope is not defined which is true.
But $scope can't be injected in a factory/service.
Any ideas?
You should handle the success or error in the controller , just return the response
checkUser: function(elUrl, classHide, classShow){
return $http.post(elUrl)
}
handle in the controller
UserService.checkUser( 'inc/memberSearch.jsp?user.Email=' + $scope.umail + '&group.PK=' + angular.element('.grp').val(),
$scope.mailexist,
'mail-exist-hide',
'mail-exist-show').then(function(){
if (!response.data.isMember) {
$scope.mailexits = 'mail-exist-hide';
$('form').submit();
} else {
$scope.mailexits = 'mail-exist-show';
return false;
}
}, function(response){
$scope.ResponseDetails = "Data: " + response.data;
});}]);
factory in MVC represents model and shouldn't be coupled with view - thing you are trying to achieve should be handled by controller
something like this should be ok:
var myApp = angular.module('mainApp', []);
myApp.factory("UserService", function ($http) {
var users = ["xxxxx", "yyyyy", "zzzzz"];
return {
all: function () {
return users;
console.log( users );
},
first: function () {
return users[1];
},
checkUser: function(elUrl, classHide, classShow){
return $http.post(elUrl);
}
};
});
myApp.controller('mainCtrl', ['$scope', '$http', 'UserService', function ($scope, $http, UserService) {
UserService.checkUser( 'inc/memberSearch.jsp?user.Email=' + $scope.umail + '&group.PK=' + angular.element('.grp').val(),
$scope.mailexist,
'mail-exist-hide',
'mail-exist-show').then(function(){
// on success
}, function(){
// on error
});
}]);
Send $scope as parameter to factory like
UserService.checkUser($scope,param1,..);
Than use this in factory
checkUser: function(scope,p1,...){
now use this scope in factory :) hope this will help
Related
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);
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;
});
})
I am trying to send an ID through to a controller using $routeParams via a factory but it is not working.
My $routeProvider:
.when('/event/:eventId', {
templateUrl : 'pages/event_detail.html',
controller : 'eventPageCtrl'
});
My factory:
myApp.factory('eventRepo', ['$http', function($http) {
var urlBase = 'php/api.php';
var eventRepo = {};
eventRepo.getEvent = function (id) {
return $http.get(urlBase + '?eventID=' + id);
};
return eventRepo;
}]);
My Controller:
myApp.controller('eventPageCtrl', ['$scope', '$routeParams', 'eventRepo',
function ($scope, $routeParams, eventRepo) {
$scope.getEvent = function (id) {
eventRepo.getEvent($routeParams.eventId)
.success(function (data) {
$scope.eventsDetail = data;
})
.error(function (error) {
$scope.status = 'Error retrieving event! ' + error.message;
});
};
}]);
When handling $http.get() inside the controller and not with the factory it works fine so I think I am not passing my $routeParams correctly? Perhaps this line is causing the issue eventRepo.getEvent($routeParams.eventId)?
This works currently, but trying to use $http.get() outside the controller:
myApp.controller('eventPageCtrl', function($scope, $http, $routeParams) {
$http.get("php/api.php?eventID="+$routeParams.eventId).success(function(data){
$scope.eventsDetail = data;
});
});
how about using resolve in your routeProver and returning the eventId and then injecting it in the controller .. example :
$routeProvider:
.when('/event/:eventId', {
templateUrl : 'pages/event_detail.html',
controller : 'eventPageCtrl',
resolve : {
eventId: function($route, $location) {
var eventId = $route.current.params.eventId;
return eventId;
});
Controller:
myApp.controller('eventPageCtrl', ['$scope', 'eventId', 'eventRepo',
function ($scope, eventId, eventRepo) { //add it as a dependency
$scope.eventId = eventId; //you can check this to see if its being assigned
$scope.getEvent = function (eventId) { //Edit: eventId added here
eventRepo.getEvent(eventId) //Edit: eventId passed
.success(function (data) {
$scope.eventsDetail = data;
})
.error(function (error) {
$scope.status = 'Error retrieving event! ' + error.message;
});
};
}]);
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...
})}]);
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;
}]);