How to pass object to angularjs controller using MVC controller Action - angularjs

I want to send object to angularjs Controller using MVC Controller Action is it possible?
suppose
public ActionResult Dashboard()
{
return View();
}
I want to pass object to app.js how to do this

Your question is a bit vague , you need to be more specific on what exactly you are trying to do.
Generally , this his how you would get data in Angular from the MVC application.
In Case of MVC/WebAPI , you should use actions to return JSON result back to the angular service which can then be processed by angular.
Example below :
app.factory('myService', function($http) {
var myService = {
GetData: function() {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get('<ActionURL>').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;
});
app.controller('MainCtrl', function( myService,$scope) {
// Call the async method and then do stuff with what is returned inside our own then function
myService.GetData().then(function(d) {
$scope.data = d;
});
});
After this services is called from the MainCtrl , angular will have the data from the MVC action available in its $scope.data variable.

Related

How to pass $http data from Service to Controller in AngularJS

AngularJS not working when I pass controller to the view
I have a problem and I can't troubleshoot it. In my simple app (very simple) I have a service that provides of users info. In angular I have an mvc which is trying to bind the info into the view.
The problem: when I pass the controller to the view, in the route directive, angular stops working in the view. I'm using a simple test {{1+1}} to verify if angular is working.
controller:
App.controller("loginController", function ($scope, usersModel) {
$scope.users = usersModel.getUsers();
})
model
App.service("usersModel", function () {
this.getUsers = function ($scope) {
$http.get("http://localhost:50765/api/users");
}});
The service should inject the $http service and return the promise that it returns
App.service("usersModel", function ($http) {
this.getUsers = function () {
return $http.get("http://localhost:50765/api/users");
}
});
And extract the data from the promise:
App.controller("loginController", function ($scope, usersModel) {
var promise = usersModel.getUsers();
promise.then(function(response) {
$scope.users = response.data;
});
})

Execute code within a factory when needed, not when loaded into controller

Factory:
.factory("myFac", ['$http', '$q', function($http, $q) {
var defer = $q.defer();
$http.get('some/sample/url').then(function (response) { //success
/*
* Do something with response that needs to be complete before
* controller code is executed.
*/
defer.resolve('done');
}, function() { //error
defer.reject();
});
return defer.promise;
}]);
Controller:
.controller("testCtrl", ['$scope', 'myFac', function($scope, myFac) {
/*
* Factory code above is executed immediately as 'myFac' is loaded into controller.
* I do not want this.
*/
if($scope.someArbitraryBool === true) {
//THIS is when I want to execute code within myFac
myFac.then(function () {
//Execute code that is dependent on myFac resolving
});
}
}]);
Please let me know if it is possible to delay the code in the factory until I need it. Also, if there's a better way to execute on this concept, feel free to correct.
You factory has $http.get directly inside factory function which return custom $q promise. So while you inject the factory dependency inside your controller function, it ask angular to create an object of myFac factory function, while creating object of function it executes the code block which you have returned your factory, basically which returns promise.
What you could do is, just return a object {} from the factory function which will have method name with its definition, so when you inject inside angular controller it will return service object, which will various method like getData method. And whenever you want to call the method of factory you could do factoryName.methodName() like myFac.getData().
Also you have created a extra promise inside your service which is not needed in first place, as you can utilize the promise of $http.get (which returns a promise object.)
Factory
.factory("myFac", ['$http', function($http) {
var getData = return $http.get('some/sample/url').then(function (response) { //success
return 'done'; //return to resolve promise with data.
}, function(error) { //error
return 'error'; //return to reject promise with data.
});
return {
getData: getData
};
}]);
Controller
.controller("testCtrl", ['$scope', 'myFac', function($scope, myFac) {
if($scope.someArbitraryBool === true) {
//Here you could call the get data method.
myFac.getData().then(function () {
//Execute code that is dependent on myFac resolving
});
}
}]);

How to exchange AJAX data between 2 controllers in AngularJS

I have 2 controllers (Products) and (ProductsFilters) and 1 service (ProductService).
The 2 controllers are being loaded at the same time as the 2nd one (ProductsFilter) acts as a side menu for the first controller (Products).
Products controller calls AJAX service through ProductService and assign the returned data to a variable(Facets) in ProductService.
At same time the the ProductsFilter retrieve the (Facets) from ProductService.
The problem now, that I want to process some data in ProductsFilter controller before it is getting displayed in the view, but at the time of execution, the ProductService.Facets return an empty object because the AJAX call has not been finished yet!
I tried to $watch() the ProductService.Facets but it didn't work.
Here is the product service
.factory('ProductService', function(AppService, CategoryService, $stateParams, $location, $http) {
return {
facets: {},
browse: function(category_id, page, order, order_type) {
url = AppService.apiUrl() + 'products/browse.json?' + params;
var that = this;
return this.getProducts(url).then(function(response) {
that.facets.grouped_brands = response.grouped_brands;
that.facets.grouped_categories = response.grouped_categories;
that.facets.grouped_prices = response.grouped_prices;
that.facets.grouped_stores = response.grouped_stores;
return response;
});
},
getProducts: function(url) {
return $http.jsonp(url + '&callback=JSON_CALLBACK&ref=mobile_app', {cache: true})
.then(function(response) {
if (typeof response.data === 'object') {
return response.data;
}
});
}
}
})
Here is the Products controller:
.controller('ProductsController', function($scope, ProductService) {
$scope.page = 1;
$scope.moreProducts = function() {
ProductService.browse(180, $scope.page)
.then(function(products) {
angular.extend($scope.products, products.products);
$scope.page +=1;
}
);
}
$scope.products = {}
})
And here is the ProductsFilter controller:
.controller('ProductsFiltersController', function($scope, ProductService) {
$scope.facets = ProductService.facets;
$scope.brand_facets = []
$scope.$watch('facets', function() {
angular.forEach($scope.facets.grouped_brands, function(value, key) {
$scope.brand_facets.push({brand: key, count: value})
});
});
})
You can use angulars $broadcast and $on functionality to tell the second controller when the ajax answer is recieved.
How to exactly implement the broadcast feature depends on the relation between your controllers. You can use this SO-answer as help: $scope.$emit and .$on angularJS
It sounds like you have an asynchronous bug in your service. You either need to have the callback of the AJAX request return the data to the controllers, or use the $q to create a promise, which is returned to the controllers.
https://docs.angularjs.org/api/ng/service/$q
$q allows you to create a deferred object. So instead of the service returning a null object, it will return a promise that your controller can act on once it has been fulfilled.

update a service variable within an $http callback

I'm using a service to make user data available to various controllers in my Angular app. I'm stuck trying to figure out how to use the $http service to update a variable local to the service (in my case "this.users"). I've tried with and without promises. The server is responding correctly.
I've read several excellent articles for how to use $http within a service to update the scope of a controller. The best being this one: http://sravi-kiran.blogspot.com/2013/03/MovingAjaxCallsToACustomServiceInAngularJS.html. That does not help me though because it negates the benefits of using a service. Mainly, modifying the scope in one controller does not modify throughout the rest of the app.
Here is what I have thus far.
app.service('UserService', ['$http', function($http) {
this.users = [];
this.load = function() {
var promise = $http.get('users.json')
.success(function(data){
// this.users is undefined here
console.log(this.users);
}
};
promise.then(function() {
// this.users is undefined here
console.log('this.users');
});
}]);
Any help is greatly appreciated. Thank you.
Try using
var users = [];
rather than
this.users = [];
and see what
console.log(users);
outputs in each of those cases.
Your service is oddly defined, but if you have a return in it you can access it from any controller:
app.service('UserService', ['$http', function($http) {
var users = [];
this.load = function() {
var promise = $http.get('users.json')
.success(function(data){
// this.users is undefined here
console.log(users);
users = data.data;
}
};
return {
getUsers: function(){
return users;
}
}
}]);
so in your controller, you can use:
var myUsers = UserService.getUsers();
UPDATE to use a service correctly here, your service should return a promise and the promise should be accessed in the controller: Here's an example from another answer I gave
// your service should return a promise
app.service('PickerService', [$http', function($http) {
return {
getFiles: function(){
return $http.get('files.json'); // this returns a promise, the promise is not executed here
}
}
}]);
then in your controller do this:
PickerService.getFiles().then(function(returnValues){ // the promise is executed here as the return values are here
$scope.myDirectiveData = returnValues.data;
});
this does not have scope anymore where you are trying to use it do this instead:
app.service('UserService', [$http', function($http) {
var users = [];
this.load = function() {
var promise = $http.get('users.json')
.success(function(data){
console.log(users);
}
};
promise.then(function() {
console.log(users);
});
}]);
all local variables to a service should just be vars if you assign them to this as a property than they will be included every time the service is injected into a controller which is bad practice.
I think what your asking for is a solution along the lines of defining your service like this:
angular.module('app')
.service('User', function($http, $q) {
var users = null;
var deferred = $q.defer()
return {
getUsers: function() {
if(users) {
deferred.resolve(users);
} else {
$http.get('users.json');
.success(function(result) {
deferred.resolve(result);
})
.error(function(error) {
deferred.reject(error);
});
}
return deferred.promise;
}
};
});
Then in one Each controller you would have to do this:
angular.module('app')
.controller('ACtrl', function($scope, User) {
User.getUsers().then(function(users) {
// Same object that's in BCtrl
$scope.users = users;
});
});
angular.module('app')
.controller('BCtrl', function($scope, User) {
User.getUsers().then(function(users) {
// Same object that's in ACtrl
$scope.users = users;
});
});
NOTE: Because the deferred.promise the same promise passed to all controllers, executing deferred.resolve(users) in the future will cause all then success callbacks in each of your controllers to be called essentially overwriting the old users list.
All operations on the list will be noticed in all controllers because the users array is a shared object at that point. This will only handle updates to the user list/each individual user on the client side of your application. If you want to persist changes to the server, you're going to have to add other $http methods to your service to handle CRUD operations on a user. This can generally be tricky and I highly advise that you check out ngResource, which takes care of basic RESTful operations

Angularjs sharing data between controllers

I have a service that fetches some client data from my server:
app.factory('clientDataService', function ($http) {
var clientDataObject = {};
var cdsService = {
fetch: function (cid) {
//$http returns a promise, which has a then function, which also returns a promise
var promise = $http.get('/clients/stats/' + cid + '/').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.
clientDataObject = {'data': response.data, 'currentClientID': cid};
return clientDataObject;
});
// Return the promise to the controller
return promise;
}
};
return cdsService;
});
Then in one controller I do:
//get stats
clientDataService.fetch($scope.id).then(function (response) {
$scope.client_data = {
'statistics': response.data
}
});
Which all works very well. However, I'm trying to do a watch from another controller on that service to update it's scope when the data changes, rather then having to re-kick off the http request:
$scope.$watch('clientDataService.clientDataObject', function (cid) {
alert(cid);
});
I'm just alerting for now, but it never ever triggers. When the page initially loads, it alerts "undefined". I have no errors in the console and all the $injects are fine, but it never seems to recognize that data has changed in the service. Am I doing something wrong in the watch?
Many thanks
Ben
clientDataService.clientDataObject is not part of your controller's scope, so you can't watch for changes on that object.
You need to inject the $rootScope into your service then broadcast the changes to the controllers scopes.
app.factory('clientDataService', function ($rootScope, $http) {
var clientDataObject = {};
var cdsService = {
fetch: function (cid) {
var promise = $http.get('/clients/stats/' + cid + '/').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.
clientDataObject = {'data': response.data, 'currentClientID': cid};
$rootScope.$broadcast('UPDATE_CLIENT_DATA', clientDataObject);
return clientDataObject;
});
// Return the promise to the controller
return promise;
}
};
return cdsService;
});
Then in the controller you can listen for the change using:
$scope.$on('UPDATE_CLIENT_DATA', function ( event, clientDataObject ) { });
Another approach can be:
define new service
app.factory('DataSharingObject', function(){
return {};
}
include this new service in controller where we want to store the data
app.factory('clientDataService', function ($http, DataSharingObject) {
DataSharingObject.sharedata = ..assign it here
}
include this new service in controller where we want to access the data
app.factory('clientReceivingService', function ($http, DataSharingObject) {
..use it here... = DataSharingObject.sharedata
}

Resources