I am new in angularjs. I am try to send a get request to my Web-Api 2 project. But I don't understand why its continuously call my method. I am following AngularJs $http for this.
Here is my error:
My Code is :
<script src="~/Scripts/jquery-2.1.0.js"></script>
<script src="~/Scripts/angular.min.js"></script>
<script>
function loginCtrl($scope, $http) {
$scope.name = function () {
console.log("Add Call");
$http({ method: 'GET', url: 'http://localhost:15229/api/values' }).
success(function (data, status, headers, config) {
console.log(data);
}).
error(function (data, status, headers, config) {
console.log(data);
});
};
}
</script>
<div lang="en" ng-app="" ng-controller="loginCtrl">
{{name()}}
</div>
You don't give enough context information for me to be sure of what you want to achieve. Especially I don't know what returns your api. So I will assume It returns the value you want to display. Your code should look more like this:
function loginCtrl($scope, $http) {
$scope.init = function () {
console.log("Add Call");
$http({ method: 'GET', url: 'http://localhost:15229/api/values' }).
success(function (data, status, headers, config) {
console.log(data);
$scope.name = data;
}).
error(function (data, status, headers, config) {
console.log(data);
});
};
}
<div lang="en" ng-app="" ng-controller="loginCtrl" ng-init="init()">
{{name}}
</div>
You should affect $scope.name in the success callback.
name should be a variable, not a function.
And the ng-init attributes defines the method to be invoked when instanciating the controller. In this case it will invoke the init() method of your controller.
Related
I'm having this situation I'm iterating over a json response from an endpoint:
chunk of controller code:
$http({
method: 'GET',
url: 'http://mywebsite.com/api/v1/stores/'
}).
success(function(data, status, headers, config) {
$scope.stores = data;
}).
error(function(data, status, headers, config) {
$scope.name = 'Error!';
});
and on my html view side I've got this:
<tbody>
<tr ng-repeat="store in stores">
<td>{{store.name}}</td>
<td> {{store.type}} </td>
<td><span ng-repeat="client in retrieveClientName(store.client_id)">
{{client.name}}
</span>
</td>
<td>{{store.address}}</td>
</tr>
</tbody>
As you can see I'm trying to retrieve the client name using a function that receives an store.client_id from the values inside the stores array. Normally using a function triggered by a ng-click will be easy but how can I achieve this "on the fly" while I'm iterating?.
Because executing this I get a kind of infinite loop that breaks all apart.
here is the code of the function that returns client name on the controller side:
$scope.retrieveClientName = function(id) {
$http({
method: 'GET',
url: 'http://mywebsite.com/api/v1/clients?client_id='+id
}).
success(function(data, status, headers, config) {
return $scope.clients=data;
}).
error(function(data, status, headers, config) {
$scope.name = 'Error!';
});
}
I have also try using mg-init directive
<td ng-init="clients=retrieveClientName(store.client_id)"><span ng-repeat="client in clients">{{client.name}}</span></td>
One way would be get all data when you get the stores back
$http({
method: 'GET',
url: 'http://mywebsite.com/api/v1/stores/'
}).
success(function(data, status, headers, config) {
$scope.stores = data;
angular.forEach($scope.stores, function(store){
$scope.retrieveClientName(store.client_id).then(function(clients){
store.clients = clients;
});
});
}).
error(function(data, status, headers, config) {
$scope.name = 'Error!';
});
Edit: I would change the structure a bit for cleaner code
$scope.retrieveClientName = function(store) { // pass in store so we can attach results here
$http({
method: 'GET',
url: 'http://mywebsite.com/api/v1/clients?client_id='+store.client_id
}).
success(function(data, status, headers, config) {
return store.clients = data; // attach result in object
}).
error(function(data, status, headers, config) {
$scope.name = 'Error!';
});
}
$http({
method: 'GET',
url: 'http://mywebsite.com/api/v1/stores/'
}).
success(function(data, status, headers, config) {
$scope.stores = data;
angular.forEach($scope.stores, function(store){
$scope.retrieveClientName(store); // no need .then here
});
}).
error(function(data, status, headers, config) {
$scope.name = 'Error!';
});
<tbody>
<tr ng-repeat="store in stores">
<td>{{store.name}}</td>
<td> {{store.type}} </td>
<td><span ng-repeat="client in store.clients"> <!-- use data here -->
{{client.name}}
</span>
</td>
<td>{{store.address}}</td>
</tr>
</tbody
You must understand that $http jest asynchronous, so Your response will be back after all ng-repeat, so such thing must be done in controller in $q.all and after that render view with ng-repeat.
So do foreach on stores and in foreach add to array, next use this array in $q.all, after $q.all render view.
The retrieveClientName function is wrong: the $http return a promise, the return value of success callback is not the return value of the function and you can't bind the ng-repeat to a promise, try this one:
$scope.retrieveClientName = function(id) {
return $resource('http://mywebsite.com/api/v1/clients?client_id='+id).query();
}
Don't forget to include the ngResource dependency.
I'm trying to read a properties file in angular, It's neccesary to have this file at the root of my project without any kind of angular stuffs, just a simple file, like java.
This is what I'm doing.
Creating a angular.properties file.
angular.properties
{
"url": "http://localhost"
}
This is my controller where I invoke my service method:
controller
captchaService
.all()
.then(function(data) {
...
}, function (data) {
...
});
This is my service class:
service
'use strict';
angular.module('app.service', [])
.factory('myService',
['$http', '$q',
function ($http, $q) {
var _URL = "";
function getValuesFromProperties() {
$http({
method : 'GET',
url : 'angular.properties'
}).success(function (data, status, headers, config) {
_URL = data.url;
}).error(function (data, status, headers, config) {
...
});
}
function all() {
getValuesFromProperties();
var deferred = $q.defer(),
promise = deferred.promise;
sessionStorage.removeItem('X_CAPTCHA_TOKEN');
$http({
method : 'POST',
url : _URL
}).success(function (data, status, headers, config) {
...
}).error(function (data, status, headers, config) {
...
});
return promise;
}
return {
all : all,
getValuesFromProperties : getValuesFromProperties
};
}]);
But here in my services class I have two $http running on an asynchronous way for that reason I can not get the value of url everything else works perfect. How can resolve this? Maybe there is another way to do this. I don't want to create a constant class because this file it's placed at the root of the project and it will be configure for others, they don't need to enter inside a lot of folders and check the code, search and edit. Any idea?
I am new to AngularJS and wanted to try out the $resource functionality.
I have this code:
.factory('GetTasksService', function($resource, BASE_URL) {
return $resource(BASE_URL + 'api/tasks');
})
.controller('TasksCtrl', function ($scope, $http, BASE_URL, GetTasksService) {
$scope.tasks = GetTasksService.query();
$scope.getTasks = function () {
$http({ url: BASE_URL + 'api/tasks', method: 'GET' })
.success(function (data, status, headers, config) {
$scope.tasks = data;
})
.error(function (data, status, headers, config) {
alert("call did not work");
});
}
});
The getTasks function works as expected - returning an array of:["taska", "taskb"] as it should.
The GetTasksService.query() however returns an array of [{"0":"t","1":"a","2":"s","3":"k","4":"a"}, {"0":"t","1":"a","2":"s","3":"k","4":"b"}]
Can anyone tell me what I am doing wrong?
There is an option when specifying an action for an ngResource called isArray;
The default action query sets this as true by default, so you need to set set the action like:
query : {
method : 'GET',
isArray : false
}
I have been trying AngularJS for a experimental project and I came along with this problem.
In my html I want to display a list of items
Index.html
<h1>Some list</h1>
<div ng-controller="datlist">
<div ng-repeat="item in items">
<div>Item description: {{item.description}}</div>
<div>Item name: {{item.name}}</div>
</div>
</div>
At first I was using a simple controller to get the information and update the view just using this:
controllers.js (original)
function datlist($scope,$http){
$http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}).
success(function(data, status, headers, config) {
$scope.items=data.itemsToReturn;
console.log(data);
}).
error(function(data, status, headers, config) {
console.log("fail");
});
}
This was working pretty well and I could get the list of items. Whilst, by changing my structure to use a factory to make the same request and bind it to $scope.items it doesn't work. I tried a lot of variations of $watch but I couldn't get it to update $scope.items. I found something about $apply but I really can't understand how to use it.
controllers.js (new one)
var datModule = angular.module('datModule',[]);
datModule.controller('datlist', function ($scope, datfactory){
$scope.items = datfactory.getlist();
$scope.$watch($scope.items, $scope.items = datfactory.getlist());
});
datModule.factory('datfactory', function ($http){
var factory = {};
factory.getlist = function(){
$http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}).
success(function(data, status, headers, config) {
console.log(data.itemsToReturn); //I get the correct items, all seems ok here
return data.itemsToReturn;
}).
error(function(data, status, headers, config) {
console.log("fail");
});
}
return factory;
});
Any ideas about this will be great.
PS: I found a lot of posts talking about this issue but none of them helped me to get a full solution.
Thanks
Using a watch for that is kinda ugly.
try this:
datModule.factory('datfactory', function ($http, $q){
this.getlist = function(){
return $http.get('http://localhost:61686/getdatlist?format=json',{'Access-Control-Allow-Origin': 'localhost:*'})
.then(function(response) {
console.log(response); //I get the correct items, all seems ok here
return response.data.itemsToReturn;
});
}
return this;
});
datModule.controller('datlist', function ($scope, datfactory){
datfactory.getlist()
.then(function(arrItems){
$scope.items = arrItems;
});
});
This is how you use promises for async matter.
UPDATE (15.01.2015): Now even sleeker!
The issue is nothing to do with the scope digest cycle. You are trying to return from inside a callback directly, which is not asynchronously possible.
I recommend you either use a promise, or return the http promise directly.
var factory = {};
factory.getlist = function(){
return $http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}});
}
return factory;
To return the promise directly, and handle the success/fail at factory.getlist().success()
Alternatively, use your own promise if you want to wrap additional logic around the request.
var datModule = angular.module('datModule',[]);
datModule.controller('datlist', function ($scope, datfactory){
$scope.items = [];
datfactory.getlist().then(function(data) { $scope.items = data });
});
datModule.factory('datfactory', function ($http, $q){
var factory = {};
factory.getlist = function(){
var defer = $q.defer();
$http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}).
success(function(data) {
// alter data if needed
defer.resolve(data.itemsToReturn);
}).
error(function(data, status, headers, config) {
defer.reject();
});
return defer.promise;
}
return factory;
});
try to initialize $scope.items = []; at controller, before call $http
I hope it helps you.
Well it looks perfect but you can use $apply like this.
datModule.controller('datlist', function ($scope, datfactory){
$scope.$apply(function() {
$scope.items = datfactory.getlist();
});
});
I think another elegant solution to this problem could be - if you are using one of the routing libraries, in my case it is the UI-Router, but could be also ngRoute, is making your controller dependent on the response of the promise, eg. adding a resolve property to the adequate state/route which doesn't let the controller load until the promise is solved and the data is ready, so in your config:
.state('datpage', {
url: '/datpage',
controller: 'DatpageController',
resolve:{
datData: function (datfactory) {
return datDataService.getData("datDataParam");
}]
},
templateUrl: 'views/datpage.html'
})
And inject the datData dependency in your controller, where you can apply it directly to the $scope:
.controller('DatpageController', function ($scope,datData) {
$scope.datPageData = datData; ...
I'm converting a server side CRUD app to Angular.js and have a small problem.
I'm getting my data with $http and display all the data via ng-repeat. I want to make users able to click and a specific item and redirect them to the resource.
So how can I pass a URL param to the $http get call dynamically?
Here's how I built the link to the resource (car.id = 3)
<a ng-href="/#/cars/{{car.id}}">Edit</a>
The link should go to http://local.dev/#/cars/3
So how do I bind the dynamic url in my controller?
Here's a stripped down version of my controller
App.controller('CarIndexCtrl', ['$scope', '$http', '$location', function ($scope, $http, $location) {
$scope.car = {};
$http({
method: 'GET',
url: $location.$$url,
})
.success(function (data, status, headers, config) {
$scope.car = data;
})
.error(function (data, status, headers, config) {
// error
});
}]);
So I'm interested to bind the URL the angular way. The above solution works, but feels very much like a hack. I'm not that familiar with Angular, so I like to stick to the defaults for now. I might consider restangular or ng-resource at a later time though...
the above solution works, but feels very much like a hack.
I don't think its hack or something messy.
I would generate URL list in controller (from my view its better for code maintenance) without appending in HTML. Something like:
$scope.urlList = [];
$http({
method: 'GET',
url: $location.$url,
})
.success(function (data, status, headers, config) {
$scope.car = data;
$scope.urlList.push("/#/cars/" + data.id);
})
.error(function (data, status, headers, config) {
// error
});
After in HTML:
<li ng-repeat="url in urlList" repeat-done="layoutDone()" ng-cloak>
<a ng-href="{{url}}">Edit</a>
</li>
BTW, I suggest you to use some loader because URL links we generate from promise (aka async) therefore with delay.
Demo Fiddle
In your app.js do something like this
var app = angular.module('YourAPP');
app.config(function ($routeProvider) {
$routeProvider
.when('/cars/:CarID', {
templateUrl: 'app/views/cars.html',
controller: 'CarIndexCtrl'
});
});
And in your controller
App.controller('CarIndexCtrl', ['$scope', '$http', '$location', '$routeParams', function ($scope, $http, $location, $routeParams) {
$scope.car = {};
$scope.carid = $routeParams.CarID;
$http({
method: 'GET',
url: $location.$$url,
})
.success(function (data, status, headers, config) {
$scope.car = data;
})
.error(function (data, status, headers, config) {
// error
});
}]);
And use the carid in wherever in your controller. Hope it helps.