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.
Related
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 trying to build a page of WordPress posts, showing 4 initially and then lazy load these in onclick of a "Load More" button. This list will be filterable via angular.
I am using the json rest api plugin for WordPress, and my angular app is currently:
var myapp = angular.module( 'myapp', [] );
// Set the configuration
myapp.run( ['$rootScope', function($rootScope) {
// Variables defined by wp_localize_script
$rootScope.api = aeJS.api;
}]);
// Add a controller
myapp.controller( 'mycontroller', ['$scope', '$http', function( $scope, $http ) {
// Load posts from the WordPress API
$http({
method: 'GET',
url: $scope.api,
params: {
'filter[posts_per_page]' : 4
},
}).
success( function( data, status, headers, config ) {
$scope.posts = data;
}).
error(function(data, status, headers, config) {});
$scope.loadmore = function(){
$scope.posts = $scope.posts.concat(data);
}
}]);
I am just a bit clueless with how to get the next 4 posts each time the load more button is clicked. I have setup a loadmore function which I am calling on click of the button:
<button ng-click="loadmore()">Load more articles</button>
Any advice would be appreciated, thanks.
Basically you need to use paging which has already implemented in wordpress API.
You need to increment your posts_per_page on each ajax call.
Controller
myapp.controller('mycontroller', ['$scope', '$http', function($scope, $http) {
var count = 0;
$scope.posts = []; //setted as blank
$scope.getData = function() {
// Load posts from the WordPress API
$http({
method: 'GET',
url: $scope.api,
params: {
'filter[posts_per_page]': 4,
'filter[page]': ++count
},
}).
success(function(data, status, headers, config) {
$scope.posts = $scope.posts.concat(data);
}).
error(function(data, status, headers, config) {});
};
$scope.loadmore = function() {
$scope.getData();
};
}]);
Done - with the help from a friend, this solution is working nicely:
var myapp = angular.module( 'myapp', [] );
// Set the configuration
myapp.run( ['$rootScope', function($rootScope) {
// Variables defined by wp_localize_script
$rootScope.api = aeJS.api;
}]);
myapp.controller('mycontroller', ['$scope', '$http', function($scope, $http) {
$scope.init = function() {
$http({ // Load posts from the WordPress API
method: 'GET',
url: $scope.api,
params: {
'filter[posts_per_page]' : 4
},
}).
success( function( data, status, headers, config ) {
$scope.posts = data;
}).
error(function(data, status, headers, config) {});
};
var page = 2;
$scope.getData = function() {
$http({ // Load posts from the WordPress API
method: 'GET',
url: $scope.api,
params: {
'filter[posts_per_page]': 4,
'page': page
},
}).
success(function(data, status, headers, config) {
$scope.posts = $scope.posts.concat(data);
page++;
}).
error(function(data, status, headers, config) {});
};
$scope.loadmore = function() {
$scope.getData();
};
}]);
we are trying to get data from service agrService with $http its working but when i reccive data to controller i am not able to access it outside that function
$scope.resource return data inside function but not outside please help.
var app = angular.module('app', ['ui.router','ngTasty']);
app.config(['$urlRouterProvider', '$stateProvider',function($urlRouterProvider, $stateProvider, $routeProvider, $locationProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
templateUrl: 'templates/home.html',
controller: function($scope, $http, $location, agrService) {
agrService.bannerSlides().then(function(data) {
//its working here
$scope.resource = data;
}, function(error) {
// do something else
});
I NEED TO ACCCESS DATA HERE CAN ANY BODY HELP
console.log($scope.resource);
}
});
}]);
app.service('agrService', function($q, $http) {this.bannerSlides = function() {
var dataUrl = 'http://WWW.EXP.COM/codeIgniter_ver/main/home';
var ret = $q.defer();
$http({
method: 'GET',
dataType: "json",
url: dataUrl
})
.success(function(data, status, headers, config) {
ret.resolve(data);
}).error(function(data, status, headers, config) {
ret.reject("Niente, Nada, Caput");
});
return ret.promise;
};
});
My suggestion would be to rethink the logic a bit. You want to do something with the data after you receive it, so why not make a function that you call once the data is received?
You'll never be able to access the resource data in that console log, simply because $http is an async call, and no matter if you return a promise or not, it's simply not ready at that point.
However, if you use it in a template or elsewhere that uses angular's double binding, it will work just fine.
To fix your issue, you can define a function with what happens after that service call and simply call it from the success callback:
agrService.bannerSlides().then(function(data) {
//its working here
$scope.resource = data;
myAfterFunction(); // <--- here
}, function(error) {
// do something else
});
and the function can be:
function myAfterFunction() {
console.log($scope.resource);
}
And btw. your service is an example of deferred antipattern, you can simply do this:
app.service('agrService', function($q, $http) {this.bannerSlides = function() {
var dataUrl = 'http://WWW.EXP.COM/codeIgniter_ver/main/home';
return $http({
method: 'GET',
dataType: "json",
url: dataUrl
})
};
});
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 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.