How to call a API in Angular controller - angularjs

I'm facing a problem with angular JS Controller function. I have a controller and in that controller I have bunch of functions which are getting called from a service which contains HTTP get and post requests.
To be specific my question is inside a controller, when I try to write:
$scope.functionName = function()
{
//some code
}
My function doesn't get called at all. And when I do the following my function gets called but the scope goes undefined for rest of the functions.
app.controller("ControllerName", function ($scope, ServiceName) {
getAll();
getAppKey();
getAppDefaults();
function getAll(){//some code}
function getAppKey(){//some code}
function AppDefaults(){//some code
})
I'm not sure where I'm going wrong. I would really appreciate anyone's help who can help me out with this issue.

I think you are defining function with $scope and calling function without $scope.
This code will work:
app.controller("ControllerName", function ($scope, ServiceName) {
$scope.getAll = function{
console.log("function called");
}
$scope.getAll();
})
And this code will not work as expected:
app.controller("ControllerName", function ($scope, ServiceName) {
$scope.getAll = function{
console.log("function called");
}
getAll();
})

'...bunch of functions which are getting called from a service...' ?
You can't call function from controller in service. What you can do is to use functions from service in controller.
If you want to use methods from service inside your controller, first inject service(you already did that),
then call it:
ServiceName.getAll();
ServiceName.getAppKey();
...
etc.
If you want to use this functions from controller, make another service/factory put this functions inside that service, inject service2 in service and again you can use them like:
ServiceName2.getAll();
ServiceName2.getAppKey();

I am not sure what are you trying to acomplish, maybie this?
this code works:
app.controller('MainCtrl', function($scope) {
$scope.submit = function() {
alert("called.........");
}
defaultFunction = function() {
alert("defaultFunction called.........");
}
defaultFunction();
});
$scope is added when you want to use in view, if you need to use it in controller, no need for $scope
you can change http://jsfiddle.net/B9RsQ/45/ to test it

Related

What does this return statement do inside a service

Im going through one of the Pluralsight courses on AngularJS with MVC5 and one of the services has this as a return statement and it looks rather strange. Im not sure what this is doing
return {
insertEmployee: insertEmployee,
updateEmployee: updateEmployee,
getEmployee:getEmployee
};
the insert/update/get names are names of methods in the service, but I dont understand the return statement. What is this doing?
It returns an object with those methods available, example:
var methods = {
insertEmployee: insertEmployee,
updateEmployee: updateEmployee,
getEmployee:getEmployee
}
Now you can do:
methods.insertEmployee(); //etc...
Actually calling a service/factory (Both can be used the same way actually, despite the fact they're not intended to work the same way.) is just calling a function. The function you defined.
If you do this :
Service :
var myfunction = function(){
alert("hello");
}
Without any return you will not see this function in your controller.
Controller :
myservice.myfunction(); will not work.
You need to return an object to be able to use the functions.
Service :
var myfunction = function(){
alert("hello");
}
return {
myfunction: myfunction;
}
This will allow you to use the service this way in your controller :
myservice.myfunction();
I usually prefer to use the object syntax in an other way, but this is just a matter of tastes :
Service :
var service = {};
service.myfunction = function(){
alert("hello");
}
return service;
This will also allow you to use this syntax in the controller :
myservice.myfunction();
Hope it helped, if you have anymore question, feel free to ask.
Actually you can understand it as AngularJS defines a factory like that. It just means: I want to expose the functions insertEmployee, updateEmployee, and getEmployee to the users of this factory.
Please refer to AngularJS: Service vs provider vs factory.
In this way, say, your factory name is myFactory, the usage is like:
angular.module('MyApp')
.controller('MyCtrl', ['$scope', 'myFactory', function ($scope, myFactory) {
myFactory.getEmployee();
}]);

Unexpected behaviors of promises

I've been facing a trouble while working with Factory/Service. I've created an AjaxRequests factory for all of my AJAX calls. My factory code is
.factory('AjaxRequests', ['$http', function ($http) {
return {
getCampaignsData: function () {
var campaigns
return $http.get(url).then(function (response) {
campaigns = response.data;
return campaigns;
});
}
}
}])
I've created another service in which I am injecting this factory. My service code
.service('CampaignsService', ['$rootScope', 'AjaxRequests', function ($rootScope, AjaxRequests) {
this.init = function () {
this.camps;
AjaxRequests.getCampaignsData().then(function (response) {
this.camps = response.campaigns;
console.log(this.camps); // It is showing data
})
console.log(this.camps); // But it is not working :(
};
this.init();
}])
And in my controller
.controller('AdvanceSettingsController', ['$scope', 'CampaignsService', function ($scope, CampaignsService) {
$scope.CampaignsService = CampaignsService;
}
])
I've read this article to learn promises but it is not working here. I can directly achieve it in controller and it's been working fine. But it consider as a bad coding standard to make controller thick. But when I use service and factory I stuck. My question is why I am not getting ajax data to use in my whole service ? I need to use CampaignsService.camps in my view template as well as in my whole rest script but every time I get undefined. What is happening here? I've asked the same question before but couldn't get any success. Some one please help me to understand about promises and why I am getting this type of error if I'm working same ? This type of question has already been asked before but it was working in controller. May be I am stuck because I'm using it in a service.
A big thanks in advance.
This is not a bug or some tricky functionality. Just like in any other AJAX implementation, you can only access the response data in AngularJS's $http success method. That's because of the asynchronous nature of Asynchronous JavaScript And XML.
And what you have is working.
.controller('AdvanceSettingsController', ['$scope', 'AjaxRequests', function ($scope, AjaxRequests) {
$scope.camps = [];
AjaxRequests.getCampaignsData().then(function(data) {
$scope.camps = data;
});
}
])
And then bind camps:
<div ng-repeat="camp in camps>{{camp.name}}</div>
What's bad in your implementation is that instead of grouping related stuff in services you are writing a big AjaxRequests service for everything. You should have a CampaignsService that has a getData method and inject that in your controller.
Why is this working? Because $http does a $scope.$apply for you, which triggers a digest cycle after the data is loaded (then) and updates the HTML. So before the then callback that ng-repeat is run with [] and after it it's again run but with data from the response because you are setting $scope.camps = data;.
The reason <div ng-repeat="camp in CampaignsService.camps>{{camp.name}}</div> does not work is because of function variable scoping.
The this reference inside of your then callback is not the same as the this reference outside of it.
This will work and uses the common var self = this trick:
var self = this;
this.camps = [];
this.init = function () {
AjaxRequests.getCampaignsData().then(function (response) {
// here "this" is not the one from outside.
// "self" on the other hand is!
self.camps = response.campaigns;
});
};

Call Angular directive controller method from another controller

I have a directive which is associated with one controller and the functions in my controller defined as
MyFormController.prototype.addNewRow = function addNewRow() {
//Adding row code
};
I want to call this method from another controller, possible ways?
I ve user the service and moved the code into that service which is shared across the controllers, however the service code does the DOM manipulation, and then i guess the next question would be that can we use $compile in a service test case
service or factory is used to share data between controller.so it would be best to define function in service and factory.
demo:
(function() {
angular.module('app', [])
.service('svc', function() {
var svc = {};
svc.method = function() {
alert(1);
}
return svc;
})
.controller('ctrl', [
'$scope', 'svc', function($scope, svc) {
svc.method();
}
]);
})();
You should not!!!
That defeats the whole purpose of modularity.
If possible try to make the function generic and create a service/factory. Now both the places where you need, use the same generic function defined in service and do their stuff.
Otherwise you can also look at events to make changes accordingly.
Look at this blog post:
http://ilikekillnerds.com/2014/11/angularjs-call-controller-another-controller/
Last but the worst solution is (avoid using this, this is literally an aweful way) is catching the element inside directive and getting its scope and taking the function from it.
Example,
var otherControllerFunc = $(".inside-directive").scope().yourfunc;

How to call a non-angular callback within a directive

Is there a correct way to pass a non-angular callback (preferably an anonymous function) name to a directive and then have it activated from the directive. My motivation is to interface from the directive to legacy non-angular code.
Here is what I want:
<my-Directive callback="function (param) {some-legacy-function(param)}">
and then have it activated:
app.directive('myDirective', function($scope) {
return {
scope: {
callback: '&'
}
controller: function($scope) {
$scope.someMethod = function() {
$scope.callback($scope.param);
}
}
});
Note that callback function is not defined on any scope and should preferably anonymous (but I can manage with a non-anonymous function as well).
I found one of doing this by simply passing a string and then doing an eval to call the method but after reading around I understand this approach is problematic (security wise).
Any suggestions would be appreciated.
you can wrap your legacy code inside a injectable service, so you can inject it anywhere (and replace/mock it for tests)
// here set on global for example
var legacyFunction=function(){};
//angular code (has to be loaded after your "old" script
myApp.factory('legacyFunction',function(){
return legacyFunction;
})
//now it is available anywhere in you application (directives, controllers, etc) as an injectable -here in a controller so you can bind it to a $scope for example
myApp.controller('myController',['$scope', 'legacyFunction', function($scope, func){
$scope.myFunc = func
}])

How can I call a function in a controller from outside the controller

I have a controller like this:
function MyCtrl($scope) {
$scope.doSomething = function(){
alert("Do something!");
}
}
And I have multiple views which depend on this (ie multiple of the below):
<div ng-controller="MyCtrl">
...
</div>
The problem is, the data the controller depends on needs to be loaded in the background (the controller does not load that data), and a callback (dataIsReady()) will be called after the data is ready.
function dataIsReady(){
// TODO: call the doSomething() function
}
Now, I want to basically call the doSomething() function, which is inside MyCtrl, from the dataIsReady() function. How can I do that?
I think what you need is a data service, which you can then inject into your controller. You can call a function on your data service which will handle the retrieval of the data and return a "promise" which can then be used to trigger your callback function when the data has loaded.
Have a look at the following code which is a slightly modified version from egghead.io:
Plunker Demo (w/ local storage): http://plnkr.co/edit/9w2jTg?p=preview
var myApp = angular.module('myApp', []);
myApp.factory('AvengersService', function ($http) {
var AvengersService = {
getAsyncCast: function () {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get("avengers.json") // or some JSON service
.then(function (response) {
// The 'then' function here is an opportunity to modify the 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 AvengersService;
});
myApp.controller('AvengersCtrl', function($scope, AvengersService) {
// Call the async method and then do something when the data is retrieved
AvengersService.getAsyncCast()
.then(function (asyncData) {
// Callback logic that depends on the data goes in here
console.info("Cast pulled async.");
$scope.avengers.cast = asyncData;
});
});
Hope that helps.
Notice: This approach in this answer is terribly wrong, one should not access to the scope of a controller outside of angular, or outside of controller at all. This would also be terribly slow if you try to call it several times. Other than that, it is fine. I am giving this answer because it is also the simplest way. I would never use that kind of code in production, though. The appropriate way is to write a service to communicate with the controller.
Given that you have defined $scope.doSomething in MyCtrl:
var scp = angular.element('[ng-controller="MyCtrl"]').scope();
scp.doSomething();
Will call doSomething method defined in the controller.

Resources