I have the following states as part of an AngularJS app:
.state('app.stages', {
url: '/stages',
views: {
'menuContent': {
templateUrl: 'templates/stages.html',
controller: 'StagesCtrl'
}
}
})
.state('app.stage', {
url: '/stages/:stageId',
views: {
'menuContent': {
templateUrl: 'templates/stage.html',
controller: 'StageCtrl'
}
}
The controllers associated are:
controller('StagesCtrl', function($scope,$http) {
$http.get("http://localhost/apistages")
.then(function(response) {
$scope.stages = response.data;
});
})
.controller('StageCtrl', function($scope, $http, $stateParams) {
$http({
method: 'GET',
url: 'http://localhost/apistage/',
params: {stageId: $stateParams.stageId}
}).then(function successCallback(response) {
$scope.stage = response.data;
}, function errorCallback(response) {
});
});
The stages list works well, but the query in the stage controller tries to access http://localhost/apistage/?stageId=43 which results in a 500 (Internal Server Error).
The URL format that I need to use is http://localhost/apistage/43 . How can I adjust the query to fetch that URL?
Then don't use params options on $http GET request. Instead just use simple string concatenation on URL while making call to service
$http({
method: 'GET',
url: 'http://localhost/apistage/'+$stateParams.stageId //append state parameter in URL itself
})
For REST API I'd highly recommend you to use ngResource($resource) module of angular. Which has good capability to deal with rest calls.
You should not use two controllers. Use only one controller and use $routeParams to get the url parameter. Here now you check if parameter is present or not and differentiate your logic as required. You can use the following code:
var stageId = $routeParams.stageId;
If(stageId)
Do something
else
Do something different
Related
I wrote a controller for login page. Here is my controller:
var authApp = angular.module('loginApp', [])
authApp.controller('LoginCtrl', ['$scope', '$location', 'loginFactory', function($scope, $location, loginFactory){
$scope.authenticate = function() {
loginFactory.login($scope.username, $scope.password)
.then(function(response) {
console.log(response.$statusText);
}, function errorCallBack(response) {
console.log(response.$statusText);
});
}
}]);
My service:
authApp.factory("loginFactory", function ($http) {
return{
login: function(username, password) {
var data = "username="+username+"&password="+password+"&submit=Login";
return $http({
method: 'POST',
url: 'http://localhost:8080/login',
data: data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
}
});
}
When I debug the code, authentication seems successful and it did get into then function. However nothing displays in console. And I got a warning(?) saying undefined for the line console.log(response.$statusText);. It is not an error since it is not red. Why doesn't it print out anything?
Use response.statusText not response.$statusText. The documentation for AngularJS $http requests lists statusText as one of the properties of the response object - https://docs.angularjs.org/api/ng/service/$http
I am new to AngularJS. I have included the code for the controller, service, and call to the rest service. Kindly advise why the call is not reaching the rest service.
My code is as follows:
app.config(function ($routeProvider) {
$routeProvider
.when('/addNewNote', {
controller: 'AddNewNoteController',
templateUrl:'views/addNote.html'
})
the angularjs controller is as below
app.controller('AddNewNoteController', ['$scope','savenote', function($scope,savenote) {
savenote.success(function(eData){
$scope.msg = eData;
The angular service to call the http post rest service
app.factory('savenote',['$http',function($scope,$http){
return $http({
method: 'POST',
url: <url is pasted here>,
dataType: 'json',
data: {
"title" : "123dddd",
"contents" : "123ddddtttttt"
},
headers: { 'Content-Type': 'application/json; charset=UTF-8' }
})
}]);
This is the rest service
#Path("/savenote")
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public UserMessages saveNewNote(Note note) throws IOException {
.....
}
You forgot the type hint for $scope:
app.factory('savenote',['$scope', '$http', function($scope,$http){
Also, your factory should return an object with methods:
app.factory('savenote', ['$scope', '$http', function ($scope, $http) {
return {
save: function () {
return $http({
method: 'POST',
url: "<url is pasted here>",
dataType: 'json',
data: {
"title": "123dddd",
"contents": "123ddddtttttt"
},
headers: {'Content-Type': 'application/json; charset=UTF-8'}
});
}
};
}]);
And use it as follows:
savenote.send().then(function(eData) {});
Also, as #SarjanDesai stated in his comment, $scope is not used in your factory, so you should remove it.
savenote returning $http object which has then function for calling success and failure callback.
So update your controller function with below:
savenote.then(function successCallback(eData) {
$scope.msg = eData;
}
The $http legacy promise methods success and error have been
deprecated. Use the standard then method instead. If
$httpProvider.useLegacyPromiseExtensions is set to false then these
methods will throw $http/legacy error.
Can't get array by $resource. Can you help me? When I use $http all is well
I have error in console:
TypeError: undefined is not a function
at http://127.0.0.1:9000/bower_components/angular-resource/angular-resource.js:597:29
at forEach (http://127.0.0.1:9000/bower_components/angular/angular.js:327:18)
at angular.module.provider.$get.Resource.(anonymous function).$http.then.value.$resolved (http://127.0.0.1:9000/bower_components/angular-resource/angular-resource.js:595:19)
at deferred.promise.then.wrappedCallback (http://127.0.0.1:9000/bower_components/angular/angular.js:11616:81)
at http://127.0.0.1:9000/bower_components/angular/angular.js:11702:26
at Scope.$get.Scope.$eval (http://127.0.0.1:9000/bower_components/angular/angular.js:12797:28)
at Scope.$get.Scope.$digest (http://127.0.0.1:9000/bower_components/angular/angular.js:12609:31)
at Scope.$get.Scope.$apply (http://127.0.0.1:9000/bower_components/angular/angular.js:12901:24)
at done (http://127.0.0.1:9000/bower_components/angular/angular.js:8487:45)
at completeRequest (http://127.0.0.1:9000/bower_components/angular/angular.js:8703:7)
I created a factory with method
coeffsResource.factory("CoeffsResources",['$resource',
function($resource) {
return $resource('/api/:action',{}, {
get_all_coeffs: { method:'GET', isArray:false, params: {action: 'getAllRegionCoefficients'} },
save_all_coeffs: { method:'POST', params: {action: 'storeAllRegionCoefficients'} },
get_manufacturer: { method: 'GET', isArray:true, params: {action: 'getAllManufacturers'} },
get_models: { method: 'GET', params: {action: 'getModels'} },
get_classes: {method: 'GET', params: {action: 'getClassesConfig'} },
get_regions: {method: 'GET', params: {action: 'getAllRegions'} },
get_ages_config: {method: 'GET', params: {action: 'getAgesConfig'} },
get_odometer: {method: 'GET', params: {action: 'getOdometersConfig'} },
get_tax_config: {method: 'GET', params: {action: 'getTaxConfig'} }
}, {stripTrailingSlashes: false})
}]);
Include factory in controller
angular.module('etachkaEvaluatorFrontendApp')
.controller('CoeffCtrl', function($scope, $http, $resource, $q, CoeffsResources) {
var coeffsResourcesObject = new CoeffsResources();
coeffsResourcesObject.$get_manufacturer().then(function() {
}, function() {
})
})
I think you need to inject the ngResource dependency.
angular.module('etachkaEvaluatorFrontendApp', ['ngResource'])
Why are you newing up a singleton? AngularJS Factories are not intended to work this way. See the AngularJS service docs for more information
Angular services are:
Lazily instantiated – Angular only instantiates a service when an
application component depends on it.
Singletons – Each component
dependent on a service gets a reference to the single instance
generated by the service factory.
Change your usage in CoeffCtrl to the following... (this also assumes you have correctly loaded the ngResource module at some earlier point in your application)
.controller('CoeffCtrl', function($scope, $http, $resource, $q, CoeffsResources) {
CoeffsResources.$get_manufacturer().then(function() {
}, function() {
})
For a better understanding on factory behavior I have crafted two simple demos. Note that these are not intended to solve your issues in a copy/paste fashion - but to demonstrate what happens when we new an AngularJS factory.
JSFiddle Link - demo - correct
JSFiddle Link - demo - incorrect - TypeError: undefined is not a function
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
})
};
});
When my ng page loads containing the ng-repeat markup below, it renders the IMG tag before the iterator is populated, but because no src value is present, that generates a 404 for the partial src.
<div ng-repeat="item in preview_data.items">
<h4>{{item.title}}</h4>
<img src="{{item.thumb}}" />
</div>
Then my controller kicks in and populates it with the right list of videos.
How do I stop the HTML from getting rendered until the controller is ready with the data?
The page is called by this route:
app.config(function ($routeProvider, $locationProvider ) {
$locationProvider.html5Mode(true);
console.log('config');
$routeProvider.when("/", {
templateUrl: "/templates/createFeed.html",
controller: "CreateFeedController"
});
});
which calls a factory to get a list of videos to preview from the backend api:
app.controller("CreateFeedController", function ($scope, $route, $sce, Preview) {
var keywords = decodeURIComponent($route.current.params.keywords);
$scope.preview_data = {
keywords: keywords
}
//pass parameters to web preview API
Preview.get(keywords, function (data) {
$scope.preview_data.items = data;
});
});
app.factory('Preview', function ($http) {
return{
get: function (keywords, next) {
$http({method: 'GET', url: '/api/preview/', json:true,
params: {keywords: keywords}}
).success(function (data) {
// prepare data here
//console.log(data);
next(data);
});
}
};
});
You must use the ng-src directive instead of the plain src attribute in your img tag.
From the Angular API for ng-src:
The browser will fetch from the URL with the literal text {{hash}} until Angular replaces the expression inside {{hash}}. The ngSrc directive solves this problem.
Check the ng-cloak directive.It's intended exactly for this.
http://docs.angularjs.org/api/ng.directive:ngCloak
As you know $http returns promise. Therefore your factory is async.
So factory should be like:
app.factory('Preview', function ($http, $q) {
return{
get: function (keywords, next) {
var deferred = $q.defer();
$http({method: 'GET', url: '/api/preview/', json:true,
params: {keywords: keywords}}
).success(function (data) {
deferred.resolve(data);
}).error(function() {
deferred.reject("Error ...");
});
//Returning the promise object
return deferred.promise;
}
};
});
And controller:
Preview.get(keywords) // returns promise
.then(function (result) {
$scope.preview_data.items = result;
}, function (result) {
alert("Error: No data returned");
});