How to stop $http being called multiple times in an Angular controller - angularjs

Inside my Controller I have tried to stop $http being called multiple times, but my efforts seem to be in vein.
I only want the report's items to be loaded once.
Have tried checking for items being undefined and having a timesrun variable at the top of the Controller and increasing by 1 at the bottom of it.
if ($scope.items === undefined && $scope.timesrun == 0)
{
var req = {
method: 'GET',
*snipped*
};
$http(req).success(function (data, status, headers, config) {
$scope.items = data;
}).error(function (data, status, headers, config) {
SweetAlert.swal("Error " + status, data, "error");
});
}
I have even had this in a service but the service just gets called multiple times.
I'm clearly missing a trick. I can understand the digest cycle and I do have expressions in the page that need to be checked so I can see why the controller is running multiple times, but I cannot understand how I can get it to exclude the web calls after they've run once.

Being called $http service twice or more may be due to many reasons. Few I am listing below:
Do not mention controller (see : omit ng-controller='HomePanel' in html) name in template.
If you are using ngRoute, and mentioning controller name in template, as well in route config, it may be calling twice. For example. In app.js
app.config([ '$routeProvider', '$sceProvider',
function($routeProvider, $sceProvider) {
$routeProvider.when('/', {
templateUrl : 'Home',
controller : 'HomePanel',
});
}]);
and in HTML:
<script type="text/ng-template" id="Home">
<div ng-controller="HomePanel">
</div>
</script>
Don't let you ajax call to cache. So append some random value in end of your URL.
var req =
{
method: 'GET',
url : someUrl + "&random="+ Math.random();
};
Hope this may help.

Instead of using $http in controller put it in a function in a custom service and call that function when you want to update data from controller or you can call $http in service and assign it to a variable and use that in controller.

Related

Controller is not getting call when its state is changing

I am using ui-router for routing my angular app. I have set the routing configuration but didn't want to use controller as syntax. I am using following syntax:
.state('blog',{
url: '/blog',
templateUrl: '/templates/blog.html',
controller: 'BlogController'
})
However the template is being called into my ui-view but I BlogController is not being called. I have used console.log() into my BlogController but I didn't see anything in my console. Here is my BlogController.js
app.controller('BlogController', function($scope, PostService,){
console.log(0);
PostService.getPost().then(function(post){
$scope.postModel = post;
});
console.log(1);
});
As you can see, I am using a service to call data using $http. Below is my PostService :
app.service('PostService', function ($http) {
this.getPost = function () {
return $http({
method : 'GET',
url : 'http://domain.com/wp-json/wp/v2/posts'
})
.then(function(response){
return response.data;
}, function(error){
return error;
});
};
});
I think this the problem related to the service call. I have read some post about resolve property in state method of ui-router. I have tried that but nothing has working. Can somebody please help me to get rid out of this ?
The declaration of the ui-router module is wrong
var app = angular.module('mySiteApp', [require('angular-ui-router')])
Should be,
var app = angular.module('mySiteApp', ['ui.router'])
Check this link for cors errors

What is the best way to initiate an AngularJS controller function that uses a service that make an HTTP request

I'm new on AngularJS. I would like to know what is the best way to use pure AngularJS to initiate a controller that uses a service that makes an HTTP request to an external source and as a response receives a JSON object.
The controller is being used to fetch information that will be shown as part of the landing page (welcome information).
I have tried:
In the HTML invoke the function with the ng-init, with alias for the controller and without alias.
In the controller make the explicit call to the service, and in the configuration of routes, resolve primitive to call the Service and save it a a variable at the configuration file.
In the controller receive as a parameter the response of the service and in the configuration of routes, use the resolve primitive to call the Service and save it as a variable with the name of the parameter that the controller receives.
In the controller save the response as a $scope variable, but it is always undefined an nothing is bound to the HTML. Is it necessary to create a value or a directive or something for saving an object in the scope? Also tried doing it at the service with $scope as parameter with the same results (undefined $scope variable).
These options effectively trigger the HTTP request and pass through the lines of the controller function. The problem is that the response is not available for the controller. Under debug mode I can only see that is an object but it doesn't behaves as a JSON object so can't access to none of the properties.
I used the .then at the controller, but although now the data is saved in the $scope, it shows [OBJECT OBJECT] and I can't access to the properties of the JSON object that is saved as the response of the http request. Any ideas?
The function of the service that makes the request like the following:
myAppModule.factory('ClimateService', function ($http) {
return {
getLocation: function () {
return $http.get("some_url/json")
then(function successCallback(response) {
return response.data;
}, function errorCallback(response) {
//
});
}
}
});
Under debug I can see the 200 response and the JSON of it. Content-Type:application/json; charset=utf-8
After several changes, none of them are triggering and I am getting an injection error. I have included the local angular-routes in the HTML header, fetched with bower.jason to the project at NetBeans. And included as the first dependency or parameter to the ngRoute
angular.module('app',['ngRoute', ...
angular.module('app.routes', ['ngRoute', 'app.core'])
.config(config);
angular.module('app.core', []);
By the way, the Angello project at GitHub injects neither services nor much parameters and the book doesn't cover this topic in depth.
Is it the version of AngularJS?
Uncaught Error: [$injector:modulerr]
http://errors.angularjs.org/1.4.8/$injector/modulerr?p0=app&p1=Error%3A%20%5B%24injector%3Amodulerr%5D%20http%3A%2F%2Ferrors.angularjs.org%2F1.4.8%2F%24injector%2Fmodulerr%3Fp0%3Dapp.config%26p1%3DError%253A%2520%255B%2524injector%253Anomod%255D%2520http%253A%252F%252Ferrors.angularjs.org%252F1.4.8%252F%2524injector%252Fnomod%253Fp0%253Dapp.config%250A%2520%2520%2520%2520at%2520Error%2520(native)%250A%2520%2520%2520%2520at%2520http%253A%252F%252Flocalhost%253A8383%252Fapp_demo_app%252Fbower_components%252Fangular%252Fangular.min.js%253A6%253A416%250A%2520%2520%2520%2520at%2520http%253A%252F%252Flocalhost%253A8383%252Fapp_demo_app%252Fbower_components%252Fangular%252Fangular.min.js%253A24%253A186%250A%2520%2520%2520%2520at%2520b%2520(http%253A%252F%252Flocalhost%253A8383%252Fapp_demo_app%252Fbower_components%252Fangular%252Fangular.min.js%253A23%253A251)%250A%2520%2520%2520%2520at%2520http%253A%252F%252Flocalhost%253A8383%252Fapp_demo_app%252Fbower_components%252Fangular%252Fangular.min.js%253A23%253A494%250A%2520%2520%2520%2520at%2520http%253A%252F%252Flocalhost%253A8383%252Fapp_demo_app%252Fbower_components%252Fangular%252Fangular.min.js%253A38%253A117%250A%2520%2520%2520%2520at%2520n%2520(http%253A%252F%252Flocalhost%253A8383%252Fapp_demo_app%252Fbower_components%252Fangular%252Fangular.min.js%253A7%253A333)%250A%2520%2520%2520%2520at%2520g%2520(http%253A%252F%252Flocalhost%253A8383%252Fapp_demo_app%252Fbower_components%252Fangular%252Fangular.min.js%253A37%253A488)%250A%2520%2520%2520%2520at%2520http%253A%252F%252Flocalhost%253A8383%252Fapp_demo_app%252Fbower_components%252Fangular%252Fangular.min.js%253A38%253A134%250A%2520%2520%2520%2520at%2520n%2520(http%253A%252F%252Flocalhost%253A8383%252Fapp_demo_app%252Fbower_components%252Fangular%252Fangular.min.js%253A7%253A333)%0A%20%20%20%20at%20Error%20(native)%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A8383%2Fapp_demo_app%2Fbower_components%2Fangular%2Fangular.min.js%3A6%3A416%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A8383%2Fapp_demo_app%2Fbower_components%2Fangular%2Fangular.min.js%3A38%3A391%0A%20%20%20%20at%20n%20(http%3A%2F%2Flocalhost%3A8383%2Fapp_demo_app%2Fbower_components%2Fangular%2Fangular.min.js%3A7%3A333)%0A%20%20%20%20at%20g%20(http%3A%2F%2Flocalhost%3A8383%2Fapp_demo_app%2Fbower_components%2Fangular%2Fangular.min.js%3A37%3A488)%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A8383%2Fapp_demo_app%2Fbower_components%2Fangular%2Fangular.min.js%3A38%3A134%0A%20%20%20%20at%20n%20(http%3A%2F%2Flocalhost%3A8383%2Fapp_demo_app%2Fbower_components%2Fangular%2Fangular.min.js%3A7%3A333)%0A%20%20%20%20at%20g%20(http%3A%2F%2Flocalhost%3A8383%2Fapp_demo_app%2Fbower_components%2Fangular%2Fangular.min.js%3A37%3A488)%0A%20%20%20%20at%20eb%20(http%3A%2F%2Flocalhost%3A8383%2Fapp_demo_app%2Fbower_components%2Fangular%2Fangular.min.js%3A41%3A249)%0A%20%20%20%20at%20c%20(http%3A%2F%2Flocalhost%3A8383%2Fapp_demo_app%2Fbower_components%2Fangular%2Fangular.min.js%3A19%3A463) (23:05:42:235 | error, javascrip
It's a bit tricky because you have to use promises (.then), but here's a super simple 'get' example.
On the Service:
function mainService($http) {
this.getData = function () {
return $http.get('/api/yourUrl') //a basic 'get' api call
.then(function (response) { //it takes time, so include a promise
return response.data;
});
};
}
And the Controller:
function homeController($scope, friendService) {
$scope.getData = function () {
mainService.getData()
.then(function (data) { //you also need a promise on controller
$scope.ourData = data; //finally put what you get on your scope
});
};
}
Note these examples don't show the defining of the controller and the service - let me know if you're confused.
let's suppose you'll use $http service to request data.
angular.module('app.core', [])
.controller('CoreController', CoreController);
CoreController.$inject = ['$scope', '$http'];
function CoreController($scope, $http) {
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
$scope.data = response.data;
}, function errorCallback(response) {
alert('something odd happens.');
});
};
in your html
<div ng-bind-html="data">
</div>
or if you want to fill a form input:
<input type="text" ng-model="data" />
From what I understood, I am suggesting few things to keep in mind . May be its not what you are looking for but it might help.
ng-init is called as the very first thing inside a controller. You can use promise in case you have to keep things in sync.
If you dont want to get into promise, simply do $http call from controller as it by default handles promise using .success & .error function.
You can't expect some $scope variable to be valid under html if it is inside service. Refer docs.
var mainApp = angular.module("mainApp",[]);
mainApp.controller("serviceController",function($scope,$http){
$http.get("/fetchData_url/").success(function(response){
$scope.data = response;
});
});

angularjs : Reload a controller

I have a controller I am calling an API on MVC.
This API returns me back a partial view, This partial view is associated with my controller from which I am calling the API .
Now as soon as I getting the partial view back, I am vanishing the html of the view and then re-rendering the view.
but my controller method never get initated, I guess because the controller is already initiated.
Question is can I call method of controller when it loads back.
html :
<div id="pageholder">
<-- here is my view , which I am changing thru API , and I want to re render it, and also want to perform certain controller methods -->
</div>
ANGULAR :
$http({
method: 'POST',
url: url,
data: {
config: item,
parameter: itemParametrs
}
}).success(function(data, status) {
$('#pageholder').empty();
$scope.username="username";
$('#pageholder').html(data);
});
PLEASE HELP!
You need to compile that new HTML you get. No directive or controller will be watched by Angular if you dynamically write HTML:
.success(function(data, status) {
$scope.username="username";
var $pholder = $('#pageholder');
$pholder.empty();
$pholder.html(data);
// Recompile the HTML so angular can process it
$compile($pholder)($scope);
});
PS: you will need to get the $compile service in your directive/controller (the same way you get $http)

how to share data between two controllers in angularjs

Iam trying to share the data returned by $http to another controller.
$scope.getClickData=function(dataId){
var postData={"containerInstanceId" : "3842a251-1708-4df0-b941-db27a03d91ab","fetchMetadata":true,"parameters":{"#{organizationTypeID}":"abf1c91f-fea8-4033-a731-136c339525c7"}};
$http.post('http://latest.tapplent.info/api/app/layouts/v1/container-instance/data',postData).
success(function(data, status, headers, config) {
$scope.data=data;
console.log(data.containerData[0].propertyData.NULL[0].organizationTypeName.value);
}).
error(function(data, status, headers, config) {
console.log("error");
});
}
});
app.controller('webView', ['$scope', function($scope) {
console.log($scope.data);
}]),
How can i get data to webview controller. Please help me friends how can i solve this problem.
Thanks in advance.
By Three ways.
1.) You can use Angular factory/services.
myApp.factory('unicornLauncher', ["apiToken", function(apiToken) {
return new UnicornLauncher(apiToken);
}]);
https://docs.angularjs.org/guide/providers
2.) By use of broadcast and Emit.
You can share data via $broadcast or $Emit and then catch this data in any controller via $on.
https://docs.angularjs.org/api/ng/type/$rootScope.Scope
I prefer Angular factory/services over broadcast/emit due to performance.
3.) Or you can use $rootscope. But that is least preferred as rootscope is your global scope. You should not litter your global scope.
The absolutely simplest way to do this would be to write the data to the rootScope.
$rootScope = data;
A better way would be to wrap the $http call in a service with methods to perform the call and retrieve the data and inject that into both controllers.
Other Way That I Usually Do like Angularjs Wire up a Backend 2nd last Example
controller1.js
from controller1 just pass dataId to controller2 and controller2 will contain request code that will bring data and populate in scope.
$scope.onButtonClick = function () {
$location.url('/controller2?dataId='+33);
//$scope.getClickData=function(dataId){}); add this func to controller2.js
}
This Code in controller1.js will
pass small dataId to other controller2.js
also navigate you to other controller2.js
controller2.js
app.controller('controller2', function($scope, $location)
{
var ID = $location.search();
$scope.getClickData=function(ID.dataId){
//REQUEST YOUR DATA
});
});
Note : As we remove (request/angular promise) getClickData() function
from controller1.js and add it to controller2.js .by doing this
controller2 will be responsible for its own data controller2 don't have to
depend on controller1 for data

append response from $http() to div

I'm quite new to Angularjs and I just can't figure out how to append a reply from $http() to a div(or any other element for that matter).
I've been using jQuery for a while and I know how to do it using that library, which is why I'm finding it hard to use Angular for this task.
I have a directive that uses $http.get() to get data from a PHP proxy. I'm trying to append the response from that $http() request to a div.
This is what I got right now:
app.directive('displayArticle', ['$http', '$log', function ($http, $log) {
var replyFromProxy = angular.element('<div></div>');
$http.get('gp-proxy.php').
success(function (data) {
// $log.info(data);
replyFromProxy = angular.element('<div>' + data + '</div>');
}).
error(function (data, status, headers, config) {
// $log.error(data);
// $log.error(status);
// $log.error(headers);
// $log.error(config);
});
return {
restrict: 'E',
templateUrl: 'templates/displayArticle.html',
compile: function (tElem) {
tElem.append(replyFromProxy);
}
};
}]);
displayArticle.html contains an empty div
What am I doing wrong?
Is there an easier or better way to do this?
Edit: What I'm trying to do is use gp-proxy.php to load an external page into my own webpage. The host doesn't allow CORS so this was my back-up plan.
Using ng-include in my template feels too static and not dynamic enough since I'd like to be able to load in different pages depending on what I click on in the original page.

Resources