Cannot get data from service after migrating to AngularJS 1.6.3 - javascript

After migrating to AngularJS 1.6.3, I changed my services like below:
Here is my service:
MetronicApp.factory('MyService', ['$http', function($http) {
return {
get: function(id, success, error) {
return $http.get(baseUrl + '/quotation/' + quotationid).then(success,error);
}
}
}]);
and in ui-router, I'm resolving the data like this.
data: function(MyService, $stateParams) {
return MyService.get($stateParams.id);
}
But in the controller, data comes undefined. Where am I wrong?

It is because you're not returning anything from success/error callback functions. Rather I'd suggest to remove .then(success,error); from get method. and then just call service get method
from resolve.
data: function(MyService, $stateParams) {
return MyService.get($stateParams.id);
}

We are using the following code in the service part just:
get: function(){
return $http.get(url);
}
without any callbacks applied, and in the calling code:
service.someMethod().then(function (result) {
var data = result.data;
}

Related

How use inside common provider $http in Angular 1.4?

I try to use common provider and in angular app config function set data in provider.
.provider('userData', function() {
var authUser = {};
return {
checkUser: function() {
// wish to able use $http here for request to get data from service
// save all data into 'authUser' object
// $get return 'authUser' object
},
getCookie: function(value) {
// wish to able use $http here
},
$get: function() {
// only for return object
return authUser;
}
}
})
app.config(['userDataProvider', function(userDataProvider) {
userDataProvider.checkUser();
});
.controller('headerCtrl', ['$scope', 'userData', '$http', function($scope, userData, $http) {
// use inside all controllers/directives 'userData'
});
I try to use $http as parameter in $get function -> not working: error:
$get: function($http) {
return authUser;
}
Also I can't find any valid example for using $http inside provider. Inside service/factory $http work fine, but I need to prepare data in provider from config function.
Services, factory & value aren't available at config phase by design.
You could do it in run()
app.run(['userData', function(userData) {
userData.checkUser();
});

Prevent route from loading until data is available in Angular

In the app I'm working on there is a situation in which data is pulled from a JSON file and is referenced in all subsequent routes. I want to ensure that a route does not load until this data is available, and if not available request it before loading the route. I'm trying to use a route resolve to accomplish this but am finding that the route will load regardless since the request to get the data returns a promise in the resolve. Here's an example of how the code for this is set up, is there a way to not load the route until the promise is resolved? I think the use of promises are throwing me off some.
Factory which pulls the data from the JSON file.
.factory('jsonFactory', function($q, $http) {
return {
getFormStuff: function() {
var deferred = $q.defer(),
httpPromise = $http.get('json/MasterObject.json');
httpPromise.then(function(response) {
deferred.resolve(response);
}, function(error) {
console.log(error);
});
return deferred.promise;
}
};
})
ngRoute config with resolve that checks if Model.formStuff is available and if not attempts to get it before loading the route which needs the data.
app.config(function ($routeProvider) {
$routeProvider.when('/someRoute', {
controller: 'someController',
templateUrl: 'views/someView.html',
resolve: {
getFormTemplate: function (Model, jsonFactory) {
if (!Model.formStuff) {
Model.formStuff = jsonFactory.getFormStuff();
return Model.formStuff;
} else {
return Model.formStuff;
}
}
}
})
EDIT: Adding the Model factory and controller where Model.formStuff is referenced. The Model.formStuff is dynamically added in a different controller and is not a pre-defined property...I inherited this code so not sure why it is handled like that.
angular.module('example', [])
.factory('Model', ['$resource',
function($resource) {
return {
query: function() {
return data;
},
get: function(id) {
return findById(id);
},
set: function(item) {
addItem(item);
},
put: function(item) {
updateItem(item);
},
del: function(id) {
removeItem(id);
},
getLoginUser: function(id) {
removeItem(id);
},
islogin: false
};
}
])
basic controller example showing how Model.formStuff is normally used.
angular.module(...)
.controller("someController", function(Model) {
$scope.someField = Model.formStuff[0].someProp;
var someVar = Model.formStuff.[0].otherProp;
// bunch of other code...
});
The code doesn't look that wrong. Please be sure to also handle the error case, otherwise the promise you return will never be rejected and the router will wait forever in case of some error. So you should call deferred.reject(error) in your error callback.
If you don't need any special processing on the data, you could directly return the promise of the $http.get() call like so:
getFormStuff = function() {
return $http.get('json/MasterObject.json');
}
What could possibly be the problem in your case is the controller definition. Do you inject a value named like the key in your resolve object into the controller? Otherwise the data will not be passed there...
angular.module(...)
.controller("someController", function(getFormTemplate) {
// do anything with the resolved data...
});
Another suggestion: Instead of handling the caching stuff directly in the resolve block, why not creating a special service that caches the data and just resolving like so:
resolve: {
getFormTemplate: function (MyCachingModel) {
return MyCachingModel.promiseToTemplate()
}
}
... and then moving the current logic into this caching service. This makes reasoning much clearer as your logic is not spread into the router config.

Angular JS Initialize service with different parameter dynamically

I have an app that when you select a project, it goes into the project section where it needs to load all the information and data about a project asynchronously.
I wanted to store all the data in a singleton service so I can access the data in all the project's subsections(project header, project footer, main menu, etc)
If user clicks a different project, it will need to re-initialize with different URL parameter (in this case, project_id).
app.factory('ProjectService', function($http, project_id) {
var SERVICE = {
async: function() {
var promise = $http.get('SOME URL' + project_id).then(function(response) {
return response.data;
});
return promise;
}
};
return SERVICE;
});
What is the best way to achieve this and how can I reinitialize the service with different URL parameters when user clicks a button?
Check working demo: JSFiddle
First of all, using a factory may be more suitable for your case.
You need to play with the deferred/promise manually. If the requested id is already loaded, resolve the deferred object immediately. Otherwise, send a HTTP request (in the demo I just used an public API providing fake data) and fetch the project information.
app.factory('ProjectFactory', ['$http', '$q', function ($http, $q) {
var myProject;
return {
project: function (id) {
var deferred = $q.defer();
// If the requested id is fetched already, just resolve
if (!id || (myProject && myProject.id === id)) {
console.log('get from cache');
deferred.resolve(myProject);
} else {
console.log('sending request...');
$http.get('http://jsonplaceholder.typicode.com/posts/' + id).success(function (response) {
myProject = response;
deferred.resolve(myProject);
}).error(function (response) {
deferred.reject(response);
});
}
return deferred.promise;
}
};
}]);
To use this factory:
app.controller('JoyCtrl', ['$scope', '$timeout', 'ProjectFactory', function ($scope, $timeout, ProjectFactory) {
ProjectFactory.project(1).then(function (project) {
$scope.project = project;
ProjectFactory.project(1).then(function (project) {
});
}, function (reason) {
console.log('Failed: ' + reason);
});
}]);
For your reference: $http, $q

AngularJS eager loading json file

I am new to angularJS. Sorry, If I am not clear with the question.
Here's the issue.
I have a JSON file ranging 20KB in size. When I try to load this file using 'factory' method, I am getting null value.
var app = angular.module('moonApp', []);
app.factory('MainSource', ['$http', function($http){
var data={source:null};
$http.get('/datafile.json',function(output){
data.source=output;
console.log(data.source); // it works
});
return data;
}]);
app.controller('appCtrl',['$scope','MainSource',function($scope,MainSource){
console.log(MainSource.source); // Not works - getting Null value
}]);
For the above code I am getting NULL value in the console. But If i try it inside the $http success method, it renders the json file contents.
Please help me. Thanks in advance.
I am using $resource to read json file. The following code can load a json file for you.
var app = angular.module('moonApp', ['ngResource']);
app.module('moonApp')
.service('MainSource', function($resource) {
return $resource('/datafile.json', {}, {
query: {
method: 'GET',
isArray: true
}
});
})
Now, inject and use the service in controller
app.controller('appCtrl',['$scope','MainSource',function($scope,MainSource){
MainSource.query(function (data) {
$scope.source = data;
console.log($scope.source); // hopefully you'll see the JSON data here
});
}]);
You can define a function on your MainSource factory and return a promise which you are able to resolve in your controller with the then() call. Please give this a try.
app.factory('MainSource', ['$http', function ($http) {
function getSource() {
return $http.get('/datafile.json', function () {
});
}
return {
'getSource': getSource
}
}]);
app.controller('appCtrl', ['$scope', 'MainSource', function ($scope, MainSource) {
MainSource.getSource().then(function (response) {
console.log(response);
});
}]);
Try like this:
console.log(MainSource.data.source);

Angular-UI-Router - getting content of dynamic template

I am building an angular app using angular-ui-router. The backend has a REST api that gives me the url to a form based on a ticket id. In app.js, I want to dynamically set the template based on a query to this REST service. Example:
$stateProvider
.state('form', {
url: '/form/:id',
templateProvider: function ($resource, formResolver, $stateParams) {
//formResolver calls the REST API with the form id and gets back a URL.
return formResolver.resolve($stateParams.id).then(function(url) {
return $resource(url).get();
};
},
controller: 'MyCtrl'
});
The problem is that I end up returning a promise and templateProvider requires a string of content. What I would like to do is just return the url:
$stateProvider
.state('form', {
url: '/form/:id',
//I would like to inject formResolver, but I can't
templateUrl: function (stateParams, formResolver) {
return formResolver.resolve(stateParams.id);
},
controller: 'MyCtrl'
});
But I don't get dependency injection when using templateUrl instead of templateProvider as per https://github.com/angular-ui/ui-router/wiki#wiki-templates, and I still have the problem of it returning a promise. I am thinking maybe my only solution is not to use the promise api.
Turns out there was something wrong with the way I was using $resource. I'm still not sure what. From looking at the source for angular-ui-router, the function can return a promise. I ended up copying some of the code from https://github.com/angular-ui/ui-router/blob/master/src/templateFactory.js to get the following, which works:
templateProvider: function ($http, formService, $stateParams) {
return formService.getFormUrl($stateParams.id).then(function(url) {
return $http.get(url);
}).then(function(response) {
return response.data;
})
Function for templateProvider may return promise from $resource but in the end it has to return string.
templateProvider: function (SomeService) {
var promise = SomeService.get().$promise;
promise.then(function (data) {
console.log(data) // it has to be string!
});
return promise;
}
If there is an object one of the solutions would be to make another promise.
templateProvider: function (SomeService, $q) {
var defer = $q.defer();
var promise = SomeService.get().$promise;
promise.then(function (data) {
console.log(data) // let say this is {html: '<p>some template</p>'}
defer.resolve(data.html);
});
return defer.promise;
}
SomeService returns $resource.

Categories