myfunction() function call from one controller to another in angularjs - javascript

i have used Angularjs and i wanna call getcustomer function from one controller to another controller i have so many doing gooogling but i don't have an idea that how to call that
i have write below code which i used
var app = angular.module('Napp', []);
app.controller('GetAlphabetical', function ($scope, $http) {
function getCutomers() {
$scope.loading = true;
$http.get('#Url.Content("~/Home/GetPesrons")').then(function (response) {
//var _data = angular.fromJson(response);
$scope.loading = false;
$scope.Customer = response.data; // please check the request response if list id in data object
}, function (error) {
throw error;
})
}
});
and second controller :
app.controller('MainCtrl', function ($scope, $http) {
getCutomers()
});

Mate, you will have to follow the following steps to resolve your problem. Firstly you have you create a factory
angular
.module('Napp')
.factory('CustomerFactory', ['$http', function ($http) {
var _factory = {};
_factory.getCustomers = function () {
return $http.get('#Url.Content("~/Home/GetPesrons")');
};
return _factory;
}]);
Then you can share data and functions between multiple controllers or services
GetAlphabetical Controller :
angular
.module('Napp')
.controller('GetAlphabetical', ['$scope', 'CustomerFactory', function ($scope, CustomerFactory) {
loadCustomers();
function loadCustomers() {
CustomerFactory.getCustomers().then(function (successResponse) {
$scope.Customer = successResponse.data; // please check the request response if list id in data object
}, function (errorResponse) {
throw error;
})
}
}]);
MainCtrl Controller :
angular
.module('Napp')
.controller('MainCtrl', ['$scope', 'CustomerFactory', function ($scope, CustomerFactory) {
loadCustomers();
function loadCustomers() {
CustomerFactory.getCustomers().then(function (successResponse) {
$scope.Customer = successResponse.data; // please check the request response if list id in data object
}, function (errorResponse) {
throw error;
})
}
}]);

This can be easily done by defining it as a service and injecting it as a dependency.
var app = angular.module('myApp', []);
myApp.service('helloWorldFromService', function() {
this.sayHello = function() {
return "Hello, World!"
};
});
app.controller('MainCtrl', function ($scope, $http, helloWorldFromService) {
app.controller('GetAlphabetical', function ($scope, $http, helloWorldFromService) {
Angular Service

What you want to do is to somehow communicate between two controllers. This can be easily be achieved using $broadcast & $on.
Incase there is a parent child relation between your controllers, use the following.
function firstCtrl($scope){
$scope.$broadcast('someEvent', [1,2,3]);
}
function secondCtrl($scope){
$scope.$on('someEvent', function(event, mass) {console.log(mass)});
}
If there is no parent child relationship between your controller, then inject $rootScope and broadcast using that.
related question - https://stackoverflow.com/a/14502755/1182982

Related

how to pass a variable from controller scope to factory

So I want the user to be able to change the cityName used by this service:
app.factory("getWeatherJSON", ['$http', function ($http) {
return $http.get(`https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=8c644b89f214d6bee6c2123faabfb05&units=metric`)
.then(function (data) {
return data;
})
.then(null, function (err) {
return err;
});
}]);
This is my controller (where the cityName comes from):
app.controller("mainController", ["$scope", "getWeatherJSON", function mainController($scope, getWeatherJSON) {
$scope.cityName = "Rio de Janeiro";
getWeatherJSON.then(function (data) {
const weatherData = data.data;
console.log(weatherData)
})
}])
I tried to use $scope.cityName inside the service without success like this:
return $http.get(`https://api.openweathermap.org/data/2.5/weather?q=${$scope.cityName}&appid=8c644b89f214d6bee6c2123faabfb05&units=metric`)
To achieve expected result, use below option
1. Wrap factory return in another function passing cityName
2. Use $scope.name value as parameter value i.e getWeatherJSON($scope.cityName)
Shortcut method to perform GET request.
Factory:
app.factory("getWeatherJSON", ['$http', function ($http) {
return function(cityName){
return $http.get(https://api.openweathermap.org/data/2.5/weather? q=:cityName&appid=8c644b89f214d6bee6c2123faabfb05&units=metric)
}
}]);
Controller:
app.controller("mainController", ["$scope", "getWeatherJSON", function mainController($scope, getWeatherJSON) {
$scope.cityName = "Rio de Janeiro";
getWeatherJSON($scope.cityName).then(function (data) {
const weatherData = data.data;
console.log(weatherData)
})
}])

AngularJS $scope inheritance service

I'm having some trouble with my code. I can't pass nor console.log the inherited $scope.user in my data service. As I'm having this problem also in another situation which looks the same I guess it's because of the callback.
The main Controller creates the user
.controller('mainCtrl', function ($scope, dataService) {
dataService.getUser(function (response) {
$scope.user = response.data[0];
})
The dataservice
.service('dataService', function ($http) {
this.getUser = function (callback) {
$http.get('mock/user.json')
.then(callback)
};
The navigation controller (child of mainCtrl):
.controller('navCtrl', function ($scope, dataService) {
//$scope.user = "test";
console.log ($scope.user);
dataService.getNavItems($scope.user,function (response) {
$scope.navItems = response.data;
});
As you can guess if I set $scope.user manually it works just fine.
The promise hasn't resolved yet when navCtrl is instantiated. What you can do is return the promise from $http.get instead of setting scope.user directly in the callback. And then just wrap the call to getNavItems in the promise.
This is assuming, navCtrl is a child of MainCtrl
.service('dataService', function ($http) {
this.getUser = function () {
return $http.get('mock/user.json');
}};
.controller('mainCtrl', function ($scope, dataService) {
$scope.userPromise = dataService.getUser();
})
.controller('navCtrl', function ($scope, dataService) {
$scope.userPromise.then(function(response) {
var user = response.data[0];
dataService.getNavItems(user, function (response) {
$scope.navItems = response.data;
});
});
})
The Scope will be different for the two Controllers, therefore it won't be defined in one if you defined it in the other. If you want it to work in both, just use the dataService.
.service('dataService', function ($http) {
this.getUser = function () {
$http.get('mock/user.json').then(function(data) {
this.user = data;
)}
};
Then access it in each controller separately, it will be available to both.
Seems like controllers 'mainCtrl' and 'navCtrl' have different scopes. If the scope of 'navCtrl' is a child of the scope of 'mainCtrl', you can access it with $scope.$parent.user
To trigger logging when the promise is resolved $scope.$parent.$watch('user', fucntion(newVal){console.log(newVal)})
If not, I would suggest to have some kind of context, where you would store the data used by different controllers.
To find a scope you can use angular.element('[ng-controller="mainCtrl"]').scope() even in browser console

Angular watch factory value

Say i have the following factory:
app.factory("categoryFactory", function (api, $http, $q) {
var selected = null;
var categoryList = [];
return {
getList: function () {
var d = $q.defer();
if(categoryList.length <= 0){
$http.get(api.getUrl('categoryStructure', null))
.success(function (response) {
categoryList = response;
d.resolve(categoryList);
});
}
else
{
d.resolve(categoryList)
}
return d.promise;
},
setSelected: function (category) {
selected = category;
},
getSelected: function () {
return selected;
}
}
});
now i have two controllers using this factory at the same time. Because of this both controllers has to be notified when updated for this i attempted the following:
app.controller('DashboardController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api','categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, categoryFactory) {
$scope.selectedCategory = categoryFactory.getSelected();
}]);
While my other controller looks like this:
app.controller('NavController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'FileUploader', 'categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, FileUploader, categoryFactory) {
$scope.categories = [];
categoryFactory.getList().then(function (response) {
$scope.categories = response;
});
$scope.selectCategory = function (category) {
categoryFactory.setSelected(category);
}
}]);
how ever when the NavController changed the value it was not changed in the DashboardController
My question is how can i either watch or in another way get notified when the value changes?
You can use an observer pattern, like so:
app.factory("categoryFactory", function (api, $http, $q) {
// the list of callbacks to call when something changes
var observerCallbacks = [];
// ...
function notifyObservers() {
angular.forEach(observerCallbacks, function(callback) {
callback();
});
}
return {
setSelected: function (category) {
selected = category;
// notify the observers after you change the value
notifyObservers();
},
registerObserver: function(callback) {
observerCallbacks.push(callback);
}
}
});
And then in your controllers:
app.controller('NavController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'FileUploader', 'categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, FileUploader, categoryFactory) {
// ...
// init
(function() {
categoryFactory.registerObserver(function() {
categoryFactory.getList().then(function (response) {
$scope.categories = response;
});
});
})();
}]);
This way, any time setSelected is called, it calls each callback that you've registered in observerCallbacks. You can register these from any controller since factories are singletons and they will always be in the know.
Edit: just want to add that I may have put the notifyObservers() call in the wrong area (currently in setSelected) and that I may be putting the wrong update call in the controller (currently getList) but the architecture remains the same. In the registerObserver, put whatever you want to do when the values are updated and wherever you make changes that you want observers to know about call notifyObservers()
You could follow dot rule here so that prototypal inheritance will get followed.
Basically you need to have one object inside your service that will have selected variable, And will get rid of getSelected method.
Factory
app.factory("categoryFactory", function(api, $http, $q) {
var categoryFactory = {};
categoryFactory.getList = function() {
var d = $q.defer();
if (categoryList.length <= 0) {
$http.get(api.getUrl('categoryStructure', null))
.success(function(response) {
categoryList = response;
d.resolve(categoryList);
});
} else {
d.resolve(categoryList)
}
return d.promise;
}
categoryFactory.setSelected = function(category) {
categoryFactory.data.selected = category;
}
categoryFactory.data = {
selected: null
}
return categoryFactory;
});
Controller
app.controller('DashboardController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'categoryFactory',
function($http, $scope, $sessionStorage, $log, Session, api, categoryFactory) {
//this will provide you binding without watcher
$scope.selection = categoryFactory.data;
}
]);
And then use {{selection.selected}} on html part will update a value when changes will occur in selection.

How to Redirect with MVC when calling $post in angular

So upfront, I am new to angular so I am a little lost with how I want to accomplish a redirect after I post data back to a server:
I have the following in a update:
$http.post("#Url.Action("SaveBranding", "AirlineConfig")", brandModel.model);
Then on the server I have this in my controller:
[HttpPost]
public ActionResult SaveBranding(BrandingViewModel viewModel)
{
if (IsModelStateValid())
{
var airline = GetAirlineFromAirlinePlatformId(viewModel.AirlinePlatformId);
switch (viewModel.PostAction)
{
case "Save":
BrandingViewModel.SaveEntity(viewModel, _db);
var airlineBranding = BrandingViewModel.FromEntity(_db.AirlinePlatforms.Single(x => x.AirlinePlatformId == viewModel.AirlinePlatformId).BrandingViews, viewModel.AirlinePlatformId);
return View("Branding", airlineBranding);
case "Save & Close":
BrandingViewModel.SaveEntity(viewModel, _db);
return RedirectToAction("Edit", "AirlineConfig", new { id = airline.AirlineId });
case "Cancel":
return RedirectToAction("Edit", "AirlineConfig", new { id = airline.AirlineId });
default:
return HttpNotFound();
}
}
return View("Branding"); //Replace this later
}
My routing isnt working and I am lost how to do this so I can navigate to the correct location.
Use window.location to manually redirect in the browser rather than use a server redirect.
The angular way to redirect is using $location service.
angular.module('someModule', [])
.controller('SomeController', ['$scope', '$http', '$location', someController])
function someController($http, $location) {
$scope.brandModel = {};
$scope.submit = function () {
$http.post("#Url.Action("SaveBranding", "AirlineConfig")", brandModel.model).then(function (data) {
$location.path('/url/to/path');
});
}
}
I put this answer here for completeness. I think also $location is more geared up for handling either hash urls or html5mode urls. If you use raw JavaScript, then you either use window.location.hash = "someUrl" or window.location.href = "someUrl". That could be a little caveat for not doing it the "angular" way.
I noticed also that you include that #Url.Action("", ""), when I did my Angular app with MVC in the index page I did this:
angular.module('someModule', [])
.factory('urlService', urlService)
function urlService() {
var service = {
getSaveBrandingUrl: getSaveBrandingUrl
};
return service;
function getSaveBrandingUrl() {
return '#Url.Action("", "")';
}
}
That way I can have all my other scripts separate, and they only rely on a function name so if you change the URL you don't have to go around the app changing all the links. When you inject this into the controller you would do something like:
angular.module('someModule', [])
.controller('SomeController', ['$scope', '$http', '$location', 'urlService', someController])
function someController($scope, $http, $location, urlService) {
$scope.brandModel = {};
$scope.submit = function () {
$http.post(urlService.getSaveBrandingUrl(), brandModel.model).then(function (data) {
$location.path('/url/to/path');
});
}
}
Obviously then you can tie all that up into it's own service to reduce the injection into the controller:
angular.module('someModule', [])
.factory('someControllerService', ['$http', 'urlService', someControllerService])
.controller('SomeController', ['$scope', '$location', 'someControllerService', someController])
function someController($scope, $location, someControllerService) {
$scope.brandModel = {};
$scope.submit = function () {
someControllerService.saveBranding($scope.brandModel.model).then(function (data) {
$location.path('some/url');
});
}
}
function someControllerService($http, urlService) {
var service = {
saveBranding: saveBranding
};
return service;
function saveBranding(branding) {
return $http.post(urlService.getSaveBrandingUrl(), brandModel.model).then(function (data) {
return data.data;
});
}
}

AngularJS: how to execute a method in another controller?

I've searched on Google but can't find information on how to do this properly. Seems like all the answers on Google are now outdated (using older versions of AngularJS).
I'm trying to setup two controllers on my AngularJS module. For example, the first controller is handling $http GET requests. And the second controller is displaying either a 'success' or 'error' message. I want to be able to call a method from the second controller with the success/error message that is to be displayed.
Or am I supposed to use a service/factory for this? I've read about services but can't figure out how to make something like this work.
var module = angular.module('app', []);
module.controller('ApiController', ['$scope', '$http', function ($scope, $http) {
$http.get('/api').
success(function(data){
// call AlertController('success')
}).
error(function(data){
// call AlertController('failed')
});
}]);
module.controller('AlertController', ['$scope', function ($scope) {
$scope.message = {
show_message: true,
type: 'info',
message: "Display message!"
};
}]);
Either doing it that way, or perhaps I would like to push the incoming alert onto a global object variable, and then remove it after it has been displayed.
Anyone know the proper way to set this up?
Ok let's try this - you should also check out Injecting $scope into an angular service function()
The Message service:
module.service('MessageService', function ($timeout) {
var messageQueue = [];
var DISPLAY_TIME = 5000; // each message will be displayed for 5 seconds
function startTimer() {
$timeout(function() {
// Remove the first message in the queue
messageQueue.shift();
// Start timer for next message (if there is one)
if (messageQueue.length > 0) startTimer();
}, DISPLAY_TIME);
}
function add(message) {
messageQueue.push(message);
// If this is the only message in the queue you need to start the timer
if (messageQueue.length==0) startTimer();
}
function get() {
if (messageQueue.length==0) return "";
else return messageQueue[0];
}
return { add: add, get: get };
});
You can still use this ApiService as well:
module.service('ApiService', ['$http', function ($http) {
return {
get: function(url) {
return $http.get(url);
}
};
}]);
Your Search controller:
module.controller('SearchController', ['$scope', 'ApiService', 'MessageService', function ($scope, api, messages) {
api.get('/yelp').
success(function(data){
messages.add('success');
}).
error(function(data){
messages.add('failed');
});
}]);
Your Alert controller:
module.controller('AlertController', ['$scope', 'MessageService', function ($scope, messages) {
$scope.getMessage = function() { messages.get(); }
}]);
So in your html you can have:
<div ng-controller="AlertController">
<div>{{ getMessage() }}</div>
</div>
here is how you make factory
module.factory('appService', ['$window', '$http', '$q', function(win, $http, $q) {
return{
backendcall: function(){
var deferred = $q.defer();
$http.get('/yelp').
success(function(data){
deferred.resolve(data);
}).
error(function(data){
deferred.resolve(status);
});
return deferred.promise;
}
}
}]);
and your controller will be like this
module.controller('AlertController', ['$scope', 'appService', function ($scope, appService) {
appService.backendcall().then(function(response){
$scope.message = {
show_message: true,
type: 'info',
message: "Display message!"
};
})
}]);

Categories