I'm a regular consumer of advice from Stackoverflow. It's an invaluable tool - thanks for all the help!
But this is my first question: I'm very new to Angular but I've been doing server side stuff for donkeys years.
I've got a method on a controller, which calls a server REST service. My problem is that the method is called whenever the controller is instantiated. I know there's got to be another way of declaring the function, but I've got no idea of what to search for.
Here's my html:
<html lang="en" data-ng-app="mLS" ng-controller="mLSController">
<head>....</head>
...
<li><a ng-if="userName" ng-click="Logout()">logout</a></li>
and my module (the module def is elsewhere, but it seems ok)
var app = angular.module('mLS');
app.controller('mLSController', function ($scope, $http, $window, $location) {
$http({
url: '/api/UI/GetUsername',
method: 'GET'
}).success(function (data, status, headers, config) {
$scope.userName = data;
$scope.desiredPath = $location.path();
if (!$scope.userName && $scope.desiredPath != '/Account/Login')
$window.location.href = '/Account/Login';
});
});
function Logout($http) {
$http({ url: '/api/UI/Logout', method: 'GET' });
}
//app.
// controller('mLSController', function ($scope, $http) {
// $scope.Logout = function () {
// $http({ url: 'api/UI/Logout', method: 'GET' });
// };
// });
//app.
// controller('mLSController', ['$scope', '$http', 'Logout', function ($scope, $http, Logout) {
// $scope.callLogout = function () {
// Logout();
// };
// }]).
// factory('Logout', ['$http', function (protocol) {
// protocol({ url: 'api/UI/Logout', method: 'GET' }).success(function() {
// $scope.Logout = true; });
// }]);
So my problem is that the current code:
function Logout($http) {
$http({ url: '/api/UI/Logout', method: 'GET' });
}
just isn't called at all, and if I put it on the controller, Logout() is called when the controller is instantiated. Which isn't ideal.
Please help!
If you want the Logout function to be exposed to DOM (via Angular), you need to put it on $scope. There is no other option to call it using angular directives (ng-click).
Else, if you want it to be called before your app/controller are instantiated, use native javascript's onclick() event.
Warning: if you use onclick, you cannot set $scope variables.
So, thanks to Bharat, I've got it working!
This is the solution:
var app = angular.module('mLS');
app.controller('mLSController',
// function added to the controller
function ($scope, $http, $window, $location) {
$scope.Logout = function () {
$http({ url: 'api/UI/Logout', method: 'GET' });
return ;
};
$http({ url: '/api/UI/GetUsername', method: 'GET' }).success(function (data, status, headers, config) {
$scope.userName = data;
$scope.desiredPath = $location.path();
if (!$scope.userName && $scope.desiredPath != '/Account/Login')
$window.location.href = '/Account/Login';
});
});
For completeness, I could wrap the GetUsername call in a function, but the question is answered.
I can't upvote your answer, Bharat, because I haven't asked enough questions yet, but thanks so much!
Related
// this is service where i m calling api
app.factory('users',['$http','$q', function($http , $q) {
return {
getUsers: function() {
var deferred = $q.defer();
var url = 'http://www.geognos.com/api/en/countries/info/all.jsonp?callback=JSONP_CALLBACK';
$http.jsonp(url).success(function (data, status, headers, config) {
console.log(data);
deferred.resolve(data);
}).
error(function (data, status, headers, config) {
//this always gets called
console.log(status);
deferred.reject(status);
});
return deferred.promise;
}
}
}]);
//this is my controller where i calling getUsers();
app.controller('myCtrl', function($scope, users) {
$scope.data = users.getUsers();
})
while calling it gives me error
Uncaught ReferenceError: callback is not defined(anonymous function)
Plz give me proper solution so that i can see me api data in <div>. Thanks in advance
$http already returns a promise. There is no need to form a promise of a promise. Try this:
app.factory('Users', ["$http", function($http){
return {
getUsers: function(url) {
return $http({
url: url,
method: 'JSONP'
});
}
};
}]);
Controller:
app.controller("MyCtrl", ["$scope", "Users", function($scope, Users) {
$scope.data = [];
Users.getUsers('http://www.geognos.com/api/en/countries/info/all.jsonp?callback=JSONP_CALLBACK').then(function(response){
console.log(response.data);
$scope.data = response.data;
}).catch(function(response){
console.log(response.statusText);
});
}]);
Here the scenario is a bit different as you have to declare a $window.callback function.
Code
var app = angular.module("demoApp", []);
app.factory('UserService', ['$http', function ($http, $q) {
var getUsers = function () {
var url = 'http://www.geognos.com/api/en/countries/info/all.jsonp?callback=callback';
return $http.jsonp(url);
};
return {
GetUsers: getUsers
}
}]);
app.controller("demoController",
["$scope", "$window", "UserService",
function ($scope, $window, UserService){
UserService.GetUsers();
$window.callback = function (response) {
$scope.countries = response.Results;
}
}]);
Plunkr: http://plnkr.co/edit/MFVpj1sMqJpcDg3ZwQFb?p=preview
I made an httpRequest fetch some items using following code:
factory.getBanners = function() {
$http({
method: 'GET',
url: 'http://localhost:2100/v1/items/getBanners'
}).then(function successCallback(response) {
console.log(response);
return response;
});
};
In controller I handled it as following:
store.controller('bannerCtrl', ['$scope', 'productService', function($scope, productService){
$scope.init = function() {
$scope.banners = productService.getBanners();
}
$scope.init();
}]);
In front end I tried to display data using
<div ng-controller="bannerCtrl">
<div data-ng-repeat="banner in banners">
<li> {{banner.bannerAltText}} </li>
</div>
</div>
But it doesn't display anything. Neither it gives any error on console. How can I resolve this issue. Here banners is an array whose each element contains bannerAltText.
Your getBanners-function does not work the way you think it does. It returns nothing. The return statement in the then function only returns from that then-function, not from getBanners. The problem is that you are trying to use an asynchonous function in a synchronous way. Instead make getBanners return a promise:
factory.getBanners = function() {
return $http({
method: 'GET',
url: 'http://localhost:2100/v1/items/getBanners'
}).then(function successCallback(response) {
return response.data;
});
};
And use that promise in your controller:
$scope.init = function() {
productService.getBanners().then(function(banners) {
$scope.banners = banners;
});
}
$scope.init();
A return in a in .then() will be a promise, rather than the data. here is a better way to construct your code
factory.getBanners = function() {
return $http({
method: 'GET',
url: 'http://localhost:2100/v1/items/getBanners'
});
};
.
store.controller('bannerCtrl', ['$scope', 'productService', function($scope, productService){
$scope.init = function() {
productService.getBanners()
.then(function(response) {$scope.banners = response.data});
}
$scope.init();
}]);
do you know what I am doing wrong? I want to read data from my json-file but i got the error that it canĀ“t read the property getData.
myApp.service('jsonDataService', function ($http) {
this.getData = function () {
return $http({
method: 'GET',
url: '/jsonData/Stations.json'
});
}
});
controller:
myApp.controller('IndexController', ['$scope', function ($scope, jsonDataService) {
jsonDataService.getData().then(function (msg) {
$scope.msg = msg;
console.log(msg);
});
}]);
I am using ng in Visual studio in a mvc project.
path json-file: " Visual Studio 2015\Projects\Test\WebApplication\Scripts\jsonData\Stations.json"
In the controller code which you have shared, you have not injected 'jsonDataService' service properly.
It should be:
myApp.controller('IndexController', ['$scope', 'jsonDataService', function ($scope, jsonDataService) {
jsonDataService.getData().then(function (msg) {
$scope.msg = msg;
console.log(msg);
});
}]);
I'm developing my first AngularJS app using the Google Docs API to pass it JSON data.
This is an example of the factory I'm using:
app.factory('Data', ['$http', 'apiKeys', function($http, apiKeys){
var googleDocs = 'https://spreadsheets.google.com/feeds/list/';
return {
news:function () {
return $http.get(googleDocs + apiKeys.googleDoc +'/1/public/values?alt=json', {cache: true});
},
updates:function () {
return $http.get(googleDocs + apiKeys.googleDoc +'/2/public/values?alt=json', {cache: true});
},
docs:function () {
return $http.get(googleDocs + apiKeys.googleDoc +'/3/public/values?alt=json', {cache: true});
}
}]);
I wanted to clean up a bit the code and decided to use services instead of making the calls in the controller itself. It works normally, but it's a pain in the ass the fact that I still need to write long $scopes because of the structure of the Google API. This is how I get the values in the controller:
app.controller('homeCt', ['$scope', 'Data', function ($scope, Data){
Data.news().success(function (data) {
$scope.totalNews = data.feed.entry.length;
});
}]);
Is there a way that I can set the factory service to pass me the data just using:
$scope.totalNews = Data.news()
Or at least removing the 'feed.entry'?
Data.news().success(function (data) {
$scope.totalNews = data.length;
});
Thank you very much!
example of service - resolve the success with the data you want
app.service('Data', ['$http', 'apiKeys', function($http, apiKeys){
var googleDocs = 'https://spreadsheets.google.com/feeds/list/';
this.news =function(){
return $http.get(googleDocs + apiKeys.googleDoc +'/1/public/values? alt=json', {cache: true})
.then(function(data){
return data.feed.entry.length;
});
}
}]);
the controller - since you already resolved the data in service hence..
app.controller('homeCt', ['$scope', 'Data', function ($scope, Data){
Data.news().then(function (data) {
$scope.totalNews = data;
});
}]);
working example
var app = angular.module('app', ['ionic'])
.service('Data', ['$http',
function($http) {
var googleDocs = 'https://spreadsheets.google.com/feeds/list/1aC1lUSxKatfxMKEy1erKDSAKgijSWOh77FDvKWhpwfg/1/public/values?alt=json';
this.news = function() {
return $http.get(googleDocs, {
cache: true
}).then(function(res) {
return res.data.feed.entry;
});
}
}
])
.controller('homeCt', ['$scope', 'Data',
function($scope, Data) {
Data.news().then(function(data) {
console.log(data);
})
}
]);
I'll give you a way of doing it, a way that I don't recommend at all (a service should not handle the scope), but for me it is the only way you have if you don't want to destroy the "async" of your ajax call :
app.factory('Data', ['$http', 'apiKeys', function($http, apiKeys){
var googleDocs = 'https://spreadsheets.google.com/feeds/list/';
return {
news:news,
updates: updates,
[...]
}
function news(scopeValue) {
$http.get(googleDocs + apiKeys.googleDoc +'/1/public/values?alt=json', {cache: true}).success(function(data){
scopeValue = data;
});
}]);
and then, call it that way in your controller :
Data.news($scope.totalNews);
In my Angular app I have a baseController.js class and a class exampleController.js which can access the functions defined in baseController through injecting its own scope into baseController. This allows for shared functionality between all controllers.
This is working except for in the case where I try to make a call to the getDataFromUrl() function from exampleController. While debugging I can see that getDataFromUrl() gets called, and it enters the .success() function of the $http.get() call. At that point I can see that data is a deserialized JSON object (in this case, it's an array of objects) BUT when the code finally comes back to exampleController's initArray() function the data that it ultimately recieves is no longer a deserialized object but has turned into the raw HTTP response data.
baseController.js:
// Data retrieval function for all derived controllers
$scope.getDataFromUrl = function (url) {
return $http.get(url)
.success(function (data) {
return data;
})
.error(function () {
return null;
});
};
exampleController.js:
appModule.controller('exampleController', [
'$scope', '$controller', '$http', '$window', '$location', '$timeout',
function ($scope, $controller, $http, $window, $location, $timeout) {
var base = $controller('baseController', { $scope: $scope });
// Initiate an array of data
var initArray = function (data) {
$scope.sortedArray = sortDataByDate(data);
};
// Calling function in scope defined by base controller class
$scope.getDataFromUrl('resources/data').then(function (data) {
initArray(data);
});
}]);
Why is data coming back to exampleController as an HTTP response? I want it to stay as deserialized JSON!
The success and error callbacks should no belong in your getDataFromUrl() function. Besides, you can't return data to the caller like that from an asynchronous call. Instead the function should return a promise to the $http call and then handle the success from the caller. That's one way to do it.
$scope.getDataFromUrl = function (url) {
// return a promise to the async action and handle `success` and `error` in the caller
return $http.get(url);
};
// for example
$scope.getDataFromUrl('resources/data').then(function (data) {
initArray(data);
});
// or
$scope.getDataFromUrl('resources/data').success(function (data) {
initArray(data);
}).error(function() {
alert('Server error');
});
Figured it out, I was getting raw response data because .then() doesn't fire as a result of .success() so the data that gets to the child controller was never deserialized to begin with. Here is the correct code:
baseController.js:
// Data retrieval function for all derived controllers
$scope.getDataFromUrl = function (url, successFunction) {
$http.get(url)
.success(function (data) {
successFunction(data);
})
.error(function () {
return null; // Or whatever you want to return
});
};
exampleController.js:
appModule.controller('exampleController', [
'$scope', '$controller', '$http', '$window', '$location', '$timeout',
function ($scope, $controller, $http, $window, $location, $timeout) {
var base = $controller('baseController', { $scope: $scope });
// Initiate an array of data
var initArray = function (data) {
$scope.sortedArray = sortDataByDate(data);
};
// Calling function in scope defined by base controller class
$scope.getDataFromUrl('resources/data', function (data) {
initArray(data);
});
}]);