Angular Resource error in console - angularjs

I ve got an angular resource service which then returns the data to a controller and I get all the data plus the data by name.
My application works just fine in the browser but I get a resource error in the console. Bad resource configuration.
I had a look in various questions and everyone states that I need to set the configuration property isArray to either false or true.
I have tried to do this but I still get an error.
Any ideas much appreciated.
Here is my service :
(function() {
var app = angular.module('test');
app.service('ContactResource', function($resource) {
return $resource('/contacts/:firstname', {},
{'update': {method: 'PUT'}},
{'query': { method: 'GET', isArray: true }},
{'get': { method: 'GET', isArray: false }}
);
});
}());
And here is my controller:
(function() {
var app = angular.module('test');
app.controller('contactsCtrl', function($scope, $routeParams, ContactResource) {
$scope.contacts = ContactResource.query();
$scope.singlecontact = ContactResource.get({firstname: $routeParams.firstname});
});
}());
The error I am getting is : Error: [$resource:badcfg] http://errors.angularjs.org/1.4.2/$resource/badcfg?p0=get&p1=object&p2=array&p3=GET&p4=%2Fcontacts
When I click it says :
Error in resource configuration for action get. Expected response to contain an object but got an array (Request: GET /contacts)
When I get the url is /contacts the response is :
[{EmailAddress:some#email.com, etc}]
When the url is /contacts/firstname the response is :
{EmailAddress:some#email.com,etc}

I solved the problem by adding a new controller called single controller and by separating the service into two functions. Here is how my code looks like now.
This is the service:
(function() {
var app = angular.module('test');
app.service('ContactResource', function($resource, $routeParams) {
this.all = function() {
return $resource('/contacts', {},
{'query': { method: 'GET', isArray: true }}
)};
this.single = function() {
return $resource('/contacts/:firstname', {firstname: '#firstname'},
{'query': { method: 'GET', isArray: false }}
);
}
});
}());
And the controllers :
(function() {
var app = angular.module('test');
app.controller('contactsCtrl', function($scope, $routeParams, ContactResource) {
$scope.contacts = ContactResource.all().query();
});
app.controller('singleCtrl', function($scope, $routeParams, ContactResource) {
$scope.singlecontact = ContactResource.single().query({firstname: $routeParams.firstname});
});
}());
For some reason which I am still not sure $resource wouldn't accept them into the same controller.

Related

angular resource POST method turns into options

I`m trying to make a request to an API server with $resource.
I want to make a post but angular turns post method into options and give an error like
OPTIONS http: / /l ocalhost/API.DWS/api/v1/user/login
XMLHttpRequest cannot load http:/ / localhost/API.DWS/api/v1/user/login. Response for preflight has invalid HTTP status code 405
var objectMethods = {
get: { method: 'GET' },
update: { method: 'PUT' },
create: { method: 'POST' },
remove: { method: 'DELETE' },
patch: { method: 'PATCH' }
};
var apiUrl = "http://localhost/API.DWS";
angular.module('nurby.version.services', [])
.config(function ($httpProvider) {
})
.factory('LoginService', ['$resource', '$http', function ($resource, $http) {
return $resource(apiUrl + "/api/v1/user/login", {},objectMethods);
}])
.controller('LogInController', ['$scope', '$rootScope', '$location','LoginService', '$http', function ($scope, $rootScope, $location, LoginService, $http) {
$scope.login = function (model) {
var loginObject = { Username: model.username, Password: model.password };
$http.defaults.useXDomain = true;
$http.defaults.headers['Content-Type'] = 'application/json';
$http.defaults.headers['Access-Control-Allow-Origin'] = '*';
LoginService.create({}, loginObject, function (data) {
if (data) {
toastr.success("itworks");
}
else {
toastr.error("not working")
}
})
}
}]);
you can define service.js and use it like below:
var APP_NAME = 'app';
angular.module(APP_NAME).service('WebService', ["$http", function ($http) {
this.login = function (parameters,callbackFunc)
{
$http({
url: 'api/login',
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: $.param(parameters)
}).success(function (data) {
callbackFunc(data);
}).error(function (data) {
callbackFunc([]);
});
};
and use it in your controller like below:
LoginController = ['$scope', '$http', '$location', 'WebService','$window', function ($scope, $http, $location,$WebService,$window) {
$scope.login = function(admin){
var data = {email:admin.email,password:admin.password};
$WebService.login(data,function(result){
if(result.success){
$window.location.replace("index");
}
else{
$scope.loginError = result.fail;
}
});
}
}];
The problem here is that you are specifying a complete URL beginning "http://localhost/API.DWS" and you haven't loaded the web page from the same domain (maybe you used a different port?).
This means the browser sees your request as a Cross-Domain request. It therefore sends an OPTIONS request first to ask the server whether it will permit you to send the POST. You could configure your server to respond correctly to these requests, or change your code so the web page and the api are on the same domain.
How to configure your server will depend on which server you are running. Search for CORS and your web server and you should find useful information.
Inside my controller this worked for me
var resource = $resource(
"your_api_url",
{
callback: "JSON_CALLBACK"
},
{
getData: {
method: "JSONP",
isArray: false
}
}
);
function loadRemoteData() {
$scope.isLoading = true;
resource.getData().$promise.then(
function( friends ) {
$scope.isLoading = false;
},
function( error ) {
// If something goes wrong with a JSONP request in AngularJS,
// the status code is always reported as a "0". As such, it's
// a bit of black-box, programmatically speaking.
alert( "Something went wrong!" );
}
);
}
$scope.searchResources = function() {
$scope.isLoading = true;
resource.getData().$promise.then(
function( friends ) {
$scope.isLoading = false;
},
function( error ) {
// If something goes wrong with a JSONP request in AngularJS,
// the status code is always reported as a "0". As such, it's
// a bit of black-box, programmatically speaking.
alert( "Something went wrong!" );
}
);
};

Getting an error while creating factory object

I have a module and controller which are created like :
var API_ENGINE_URL = 'localhost/angular/';
var mainApp = angular.module('mainApp', ['ngRoute', 'ngResource']);
mainApp.controller('productController', ['$scope', 'ProductFactory', 'ProductListFactory','$routeParams', function ($scope, ProductFactory,routeParams, ProductListFactory) {
var productList = new ProductListFactory();// THROWS ERROR HERE
var promise = productList.$get({id: $routeParams.category_id}).$promise;
promise.then(function (productList) {
$scope.productList = productList;
});
}]);
and the Model is created like this, files are properly loaded
mainApp.factory('ProductListFactory', ['$resource',function ($resource) {
return $resource(API_ENGINE_URL + 'category/:id/items', {}, {
get: {method: 'GET', params: {category_id: '#category_id', id: '#id'},isArray:true,url:API_ENGINE_URL+'product?store_id=:storeId'},
save: {method: 'GET', isArray: true}
});
}]);
I am getting an error in the controller like below. what could be the error. Stuck for a long time
In a factory function, the return value is what's cached and injected by Angular. There is no need to instantiate it yourself.
Try this:
mainApp.controller('productController', ['$scope', 'ProductFactory', 'ProductListFactory','$routeParams', function ($scope, ProductFactory,routeParams, ProductListFactory) {
var promise = ProductListFactory.$get({id: $routeParams.category_id}).$promise;
promise.then(function (productList) {
$scope.productList = productList;
});
}]);
Problem is in ordering should be :
['$scope', 'ProductFactory', 'ProductListFactory','$routeParams', function ($scope, ProductFactory,ProductListFactory,$routeParams)

$scope not being acessed in the view

I'm using Angular in an application. After getting a specific object (a movie in my case), I'm assigning the object to $scope ($scope.movie = response), so that I can use it in the view. The problem is that my view seems not to display anything I use in $scope. I've tried deleting everything and doing a dummy test like $scope=name="whatever" and when I use something like {{name}} in the view nothing is rendered. Have anyone faced this problem ? I've already searched for this error, and it seems like it would be a good idea to use $apply(). I've tried that and it didn't work. The function that fetches the data is below:
var app = angular.module('movies');
app.factory('Films', ['$resource',function($resource){
return $resource('/films.json', {},{
query: { method: 'GET', isArray: true },
create: { method: 'POST' }
})
}]);
app.factory('Film', ['$resource', function($resource){
return $resource('films/:id.json', {}, {
show: {method: 'GET' },
update: { method: 'PUT', params: {id: '#id'} },
delete: { method: 'DELETE', params: {id: '#id'} }
});
}]);
app.controller('MoviesController', ['$scope', '$http', '$location', '$resource', '$routeParams', 'Films', 'Film', function($scope, $http, $location, $resource, $routeParams, Films, Film){
$scope.movies = Films.query();
$scope.user = document.getElementById('name').innerHTML; // Find a better way to interact with devise via angular
$scope.createMovie = function() {
$scope.movies = Films.query();
$http.get(
'/categories.json'
).success(function(data,status,headers,config){
$scope.categories = data;
}).error(function(data, status, headers, config){
alert("There was an error while fetching the categories on the database. Error " + status);
});
$location.path("/" + 'new').replace();
};
$scope.listMovies = function() {
$location.path("/").replace();
};
$scope.save = function(){
if($scope.form.$valid){
Films.create({film: $scope.movie}, function(){
$scope.form.$setPristine();
}, function(error){
alert("Movie not created");
});
}
};
$scope.deleteMovie = function(movie){
Film.delete(movie);
$scope.movies = Films.query();
};
$scope.viewDetails = function(movie){
$scope.name="ola";
alert(movie.id);
$location.path("/" + movie.id);
var Movie = $resource('films/:filmId'+'.json', {filmId: '#id'});
$scope.movie = Movie.get({filmId: movie.id});
$scope.movie.$promise.then(
function(response){
$scope.$apply();
$scope.movie = response;
console.log("filme e: " + response.name);
},
function(error){
console.log("request failed");
}
);
};
}]);
I had a look at your repository and I think where your problem is. You are trying to reuse the MoviesController in all of your routes. But AngularJS will create a new instance for every route and therefore you can't access your previous data because it will be destroyed.
So I would start by creating a separated controller for each view, so you can move the code of your viewDetails method to a new MovieDetailController. To have access to the movie id in this controller, you need to use the $routeParams service.
angular.module('movies').controller('MovieDetailController', MovieDetailController);
function MovieDetailController($scope, $resource, $routeParams) {
var Movie = $resource('films/:filmId'+'.json', {filmId: '#id'});
Movie.get({filmId: $routeParams.id}).then(
function(response) {
$scope.movie = response;
},
function(error){
console.log('request failed');
}
);
}
Change your route definition to use the new controller.
.when('/movies/:id', {
controller: 'MovieDetailController',
templateUrl: 'movie_details.html'
})
And now your viewDetails method in the MoviesController just need to redirect to the movie detail url.
$scope.viewDetails = function(movie) {
$location.path('/movies/' + movie.id);
}
I hope it works for you. Let me know when you try!

How to save my result as indexed array?

Currently my array cust is empty but the json data (wrapped with some metadata) is successfully loaded as I can see in Chrome debugger network preview.
How to pass the result in my array, so that there are indexed and I can access them in my program?
angular.module('Cust').factory('CustomizingService', ['$resource', function ($resource) {
var url = 'http://localhost:31736/Service1.svc/:link/';
return {
Customizing: $resource(url, {callback: 'JSON_CALLBACK'}, {
customers: {
method: 'JSONP', transformResponse: function(data) {return angular.fromJson(data).body.rows},
params: { link: 'GetCustomers', numberOf: '#numberOf', valid = #valid },
isArray: true },...
My controller:
app.controller('controllerA', ['$scope', 'CustomizingService',
$scope.cust = CustomizingService.Customizing.customers({numberOf: 12, valid: true});
}]);
app.controller('controllerA', ['$scope', 'CustomizingService', function(){
CustomizingService.Customizing
.customers({numberOf: 12, valid: true}).$promise
.then(function(data){
$scope.cust = data;
},function(error){
});
}]);
I solved the problem by using the AngularJS service restangular. It is an easy way to handle Rest API Resources properly and easily.
More information here: https://github.com/mgonto/restangular.
Now I can drop ng-resource :-)
The new code:
app.controller('controllerA', ['$scope', 'CustomizingService', 'Restangular', function($scope, CustomizingService, Restangular) {
//http://localhost:31736/Service1.svc/GetCustomers?numberOf=12&valid=true
Restangular.all('Service1.svc').customGETLIST('GetCustomers',{numberOf: 12, valid: true}).then(function(result){
$scope.customers= result;
});
}]);
app.config(function(RestangularProvider){
RestangularProvider.setBaseUrl('http://localhost:31736/');
RestangularProvider.setDefaultRequestParams('jsonp', {callback:
'JSON_CALLBACK'});
});

How to use success and error in Angularjs if not using $http?

Below is my code for querying a resultset in angularjs. Below is both controller.js and services.js. However I want to get .success and .error defined in my getResult call so that I can defined different $scopes for each flow and show it on UI accordingly. I searched but everywhere I got it for $http which I am not using. As I am new to angularjs, could you please help me out with it?
app.controller('DemoCtrl3', ['$scope', 'PFactory', '$location', function ($scope, PFactory, $location) {
$scope.getResult = function () {
$scope.allposts = PFactory.postmain.query();
$location.path('/view2');
}
services.js is:
return {
postmain: $resource('/ngdemo/web/posts', {}, {
query: {method: 'GET', isArray: true },
create: {method: 'POST'}
}),
You can pass success and error callbacks to resource actions (query, create, etc.) and get response data as callback parameter. Here is an example of doing it:
HTML
<body ng-controller="ctrl">
<h1>{{message}}</h1>
</body>
JavaScript
angular.module('app',['ngResource']).
service('PFactory', ['$resource', function($resource) {
return {
postmain: $resource('data.json', {}, {
query: {method: 'GET', isArray: true },
create: {method: 'POST'}
})
}
}]).
controller('ctrl', ['$scope', 'PFactory', function($scope, PFactory) {
PFactory.postmain.query(function success(data){
$scope.message = 'Number of records loaded: '+data.length;
}, function error() {
$scope.message = 'Server Error!'
});
}]);
Plunker: http://plnkr.co/edit/k5LgMPkU6jAteaFCn74C?p=preview
AngularJS documentation: $resource

Resources