Unable to get result of asynchronous call in the controller $scope - angularjs

I was trying to improve the code in my application by moving the RESTful call in my angularJS to a factory like so:
In app.js
var myApp = angular.module('myApp', ['ngRoute','ngResource']);
In services.js
swof.factory('engineerService', function($resource)
{
var data = $resource('/api/engineers/:empid',{empid: "#empid"},
{
'get':
{ method:'GET'},
'save':
{method:'POST'},
'query':
{method:'GET',
transformResponse: function(data)
{
return angular.fromJson(data);
},
isArray:true},
'remove':
{method:'DELETE'},
'delete':
{method:'DELETE'}
});
return data;
});
In controller.js
engineerService.query().$promise.then(function(data)
{
$scope.engineers = data;
typeof $scope.engineers;
console.log("[in]", $scope.engineers);
$scope.$apply;
});
console.log("[out]", $scope.engineers);
The controller is referenced in the engineer.html page and the idea is that it will display a list of engineers from $scope.engineer.
The output in the Chrome console is as follows:
For some reason I am unable to get the data returned from the REST query to appear outside of the section of the controller with the $promise.
Can someone please help me with this?

Here is the solution. First of all the services part:
swof.factory('engineerService', function($resource)
{
var data = $resource('/api/engineers/:empid',{empid: "#empid"},
{
'get':
{ method:'GET'},
'save':
{method:'POST'},
'query':
{method:'GET',
transformResponse: function(data)
{
return angular.fromJson(data);
},
isArray:true},
'remove':
{method:'DELETE'},
'delete':
{method:'DELETE'}
});
return data;
});
Now for the controller:
swof.controller('engineerController', ['$scope', '$log', '$http', 'engSchedService', 'engineerService', function($scope, $log, $http, engSchedService, engineerService ) {
engineerService.query().$promise.then(function(data)
{
$scope.engineers = data;
});
}]);
The values in $scope.engineers was accessed in html using ngrepeat as follows:
<tbody ng-repeat="engineer in (filtered = (engineers | filter: query | filter: searchKeyword | orderBy: orderByField:reverseSort))">
Big thanks to everyone who contributed to help me with this. G

Related

Elegant way to organize and user ngResource

My app need interact with various tables and views. I'm new in angular and I can't think a elegant way to organizer the services in my app of ngResource. Any sugestions?
I think that my controller declaration is very full of services.
/app/app.resource.js
angular.module('totalizacao').factory('ldap', ['$resource', function($resource) {
return $resource('api.php/ldap/:usuario/:senha', {usuario: '#usuario', senha:''}, {
login: {
isArray: false,
method: 'POST'
}
});
}]);
angular.module('totalizacao').factory('tb_agendamentos_llpp', ['$resource', function($resource) {
return $resource('api.php/tb_agendamentos_llpp/:ID', {'ID' :''});
}]);
angular.module('totalizacao').factory('tb_atendimentos_llpp', ['$resource', function($resource) {
return $resource('api.php/tb_atendimentos_llpp/:ID', {'ID' :''});
}]);
angular.module('totalizacao').factory('tb_grupo_oferta_llpp', ['$resource', function($resource) {
return $resource('api.php/tb_grupo_oferta_llpp/', {});
}]);
angular.module('totalizacao').factory('tb_mvmt_llpp', ['$resource', function($resource) {
return $resource('api.php/tb_mvmt_llpp/', {});
}]);
ngular.module('totalizacao').factory('tb_ofertas_llpp', ['$resource', function($resource) {
return $resource('api.php/tb_ofertas_llpp/', {});
}]);
angular.module('totalizacao').factory('tb_score_llpp', ['$resource', function($resource) {
return $resource('api.php/tb_score_llpp');
}]);
angular.module('totalizacao').factory('tb_vendas_llpp', ['$resource', function($resource) {
return $resource('api.php/tb_vendas_llpp/:ID_LNHA', {ID_LNHA: ''});
}]);
angular.module('totalizacao').factory('tb_vendas_servicos_llpp', ['$resource', function($resource) {
return $resource('api.php/tb_vendas_servicos_llpp/:ID', {'ID' :''});
}]);
angular.module('totalizacao').factory('vw_agendamentos_llpp', ['$resource', function($resource) {
return $resource('api.php/vw_agendamentos_llpp/');
}]);
angular.module('totalizacao').factory('vw_arvore_ofertas_llpp', ['$resource', function($resource) {
return $resource('api.php/vw_arvore_ofertas_llpp/', {});
}]);
.
.
.
My controller
angular.module('totalizacao').controller('arvoreOferta',
['$routeParams','$rootScope','$scope','vw_vendas_llpp','vw_arvore_ofertas_llpp'
,'tb_grupo_oferta_llpp', 'tb_ofertas_llpp', 'tb_agendamentos_llpp','tb_atendimentos_llpp'
,'tb_vendas_servicos_llpp', 'vw_vendas_servicos_llpp'
,'vw_agendamentos_llpp','tb_score_llpp','vw_ofertas_totais','dateFilter'
, function($routeParams, $rootScope, $scope, vw_vendas_llpp, vw_arvore_ofertas_llpp
,tb_grupo_oferta_llpp, tb_ofertas_llpp, tb_agendamentos_llpp
, tb_atendimentos_llpp, tb_vendas_servicos_llpp, vw_vendas_servicos_llpp
, vw_agendamentos_llpp, tb_score_llpp, vw_ofertas_totais, dateFilter){
var self = this;
.
.
.
I always prefer using $http since i can have more control on making it generic, infact $resource internally uses $http. But since you have used $resource i am making an effort to do it $resource way.
Please forgive my syntaxes and compilation errors, as i am directly typing it here.
what you can do is create a common service or factory say apiService or apiFactory and then pass the required parameters, http method and action etc..
I wont go into coding details, as its upto you how generalise and what you pass, but something like this:
//First create a constant object:
angular.module('totalizacao').constant('apiConstants', {
totalizacao: 'api.php/tb_mvmt_llpp/',
totalizacao1: 'api.php/tb_mvmt_llpp1/'
});
// Generalise your factory as you want this is to give you an idea.
angular.module('totalizacao').factory('apiFactory', ['$resource','apiConstants', function($resource) {
var apiFactory = {};
/* Http Method = GET, PUT, POST;
MethodName = { 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'} };*/
apiFactory.executeApi = function(url, methodName, httpMethod, params){
var paramNames = Object.keys(params);// getKeys
//construct url
// you can put a for loop here to make it more generic for multiple params
//params[paramNames[i]] will get you the value, here i just have one
var completeUrl = url + ':' + paramNames[0]; // api.php/tb_mvmt_llpp/:paramName1
var resources = $resource(completeUrl, null, {
apiMethod: {
method: httpMethod
}
});
//you can return the promise or return the value
resources[methodName](params) ///resources['get'](params)
.$promise.then(function(user) {
// do something
});
return // resources[methodName](params).$promise or some variable after
};
return apiFactory;
});
in your controller, inject apiFactory, apiConstants and do the following
var params = {
paramName1 : 'paramValue1'
};
apiFactory.executeApi(apiConstants.totalizacao, 'get', params).then(success,error);
function success(){};
function error(){};

How to store REST api result in service to avoid requerying

service
app.factory('Notes', ['$resource', function($resource) {
return $resource('/notes/:id', {id: '#id'},
{
'query': {method: 'GET', params: { format: 'json'}, isArray: true},
'update': {method:'PUT'},
'save': {method:'POST'},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'}
},
{ stripTrailingSlashes: false}
);
}]);
Controller:
app.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes',
function($scope, $routeParams, Notes) {
$scope.notes = Notes.query();
Notes.query(
function(data) {
$scope.notes = data;
// success handler
},
function(error) {
alert('error')
// error handler
}
);
}]);
If we are using Notes service in multiple controller it will fetch data again and again.
How to avoid fetching data? I want to fetch data only once and then serve same data to every controller.

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'});
});

I don't know how to use this angularjs options

I update the question now .
Mi view HTML
<a class="btn btn-success" ng-click="eliminartodo()">Eliminar todos</a>
Now I send my Controller Angular
.controller('ListCtrl', function($scope,$routeParams,Node,User) {
$scope.nodes = Node.query();
/**DeleteAll**/
$scope.eliminartodo = function () {
$scope.nodes = [];
};
})
And my Factory
nodeServices.factory('Node', ['$resource',
function($resource){
return $resource('api/nodes/:nodeId', {}, {
'get': {method:'GET', params:{nodeId:'#nodeId'}, isArray:false},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'update': {method:'PUT'},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'}
});
}]);
In another code I use this and working properly
Node.remove({nodeId: nodeId}, $scope.node, function() {
$timeout(function() {
$location.path('/');
});
});

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