Is there anyway to create Javascript object with "default function"? AngularJS - javascript

As you may know, AngularJS $http service is allowing to call it with/out specific function, for ex:
$http(req).then(function(){...}, function(){...});
$http.get('/someUrl', config).then(successCallback, errorCallback);
I would like to get some more information about the way I can implement it on my factory and generally in JS.

Functions are Objects in JavaScript. This means that you can assign other properties and functions on a function.
function foo(){
//do something
}
foo.bar = function(){
//do something else
}

As it was mentioned above you can implement what you want using Angular's '$resource'. Here is an example of how it can be used:
app.service('testResource', ['$resource', function ($resource) {
var apiBaseUrl = 'http://test-backend/api';
var testResource = $resource(
apiBaseUrl + '/test/'
{},
{
'query': {
method: 'GET',
isArray: true
}
}
);
this.getAll = function () {
return testResource
.query()
.$promise
.then(function (data) {
var tests = [];
angular.forEach(data[0], function (value) {
tests.push(value);
});
return tests;
});
};
}]);
Then inject it in Controller (or wherever) and call it:
testResource.getAll().then(
function (data) {
$scope.tests = data;
}
);
You can also implement other methods such as POST, PUT, DELETE.

Related

Angularjs - How to implement getters and setters to Data Model?

I'm building a RESTful Webapp with an AngularJS Frontend.
I'm trying to separate the Data - received via JSON - into an Object which can be passed between controllers, following this tutorial:
http://www.webdeveasy.com/angularjs-data-model/
I'm struggling at the point "Sharing a model between controllers ".
My Problem is, that i can't reach the values from inside of the Object, and also not from the controller, which uses the Object. I 'm only able to reach the values with the {{ }} tags in the html template.
HereÅ› the Object:
(function () {
"use strict";
angular
.module('app.admin')
.factory('AdminEventFactory', AdminEventFactory);
/** #ngInject */
function AdminEventFactory($http) {
function AdminEvent(eventData) {
if (eventData) {
this.setData(eventData);
}
};
//AdminEvent Objekt
AdminEvent.prototype = {
setData: function (eventData) {
angular.extend(this, eventData);
},
load: function (id) {
var scope = this;
$http({
method: "GET",
url: "http://docker-backend.test/api/events/" + id
}).then(function mySuccess(response) {
scope.setData(response.data);
}, function myError(response) {
console.log(response);
});
},
//How to reach the values set in the load method via getter here?
getTitle: function(){
console.log(this.setData.title); //undefined
}
};
return AdminEvent;
}
}());
Here's the call from the controller:
(function () {
"use strict";
angular
.module('app.admin')
.controller('Admin.EventsController', AdminEventsController);
/** #ngInject */
function AdminEventsController( [...] , AdminEventFactory) {
[...]
function editEvent($eventId) {
var event = new AdminEventFactory();
event.load($eventId);
console.log(event);
event.getTitle(); //undefined
$scope.event = event;
}
[...]
In the HTML Template could the value be reached:
<!-- "TestTitle" -->
<div>{{ event.title }}</div>
The event logged via console:
AdminEvent {}
description: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
endDate: "2019-05-16T22:00:00+00:00"
id: 62
startDate: "2019-05-15T22:00:00+00:00"
title: "TestTitle"
> __proto__: Object
[...]
I like to reach things like title via getter and setter in the controllers, in the model and not only via template tags {{ }}.
Thank you for your help!
Have the load method return a promise:
load: function (id) {
var scope = this;
return $http({
method: "GET",
url: "http://docker-backend.test/api/events/" + id
}).then(function mySuccess(response) {
scope.setData(response.data);
return response.data
}, function myError(response) {
console.log(response);
throw response;
});
},
In the controller, use the returned promise:
function editEvent($eventId) {
var event = new AdminEventFactory();
var promise = event.load($eventId);
promise.then(function(data) {
console.log(data);
console.log(event);
event.getTitle(); //undefined
});
$scope.event = event;
}
The .then method of the promise waits for the data to arrive from the server before executing the console.log statements.

angularJS closure causes $HTTP.get to not return my array of JSON objects

I have the following 3 methods in my module.factory dataservice I am using Angular 1.5
getCannedJSON . This function works as intended and i would like the others to behave the same way. I copy and pasted the JSON i got from my webAPI in postman and put this in to the function. It returns an array of objects like i want.
getDataFromAPI. For some reason I cannot get this function to return the response. The console.log(response) has exactly the data I want aka the same data as getCannedJSON. Instead it returns a d {$$State: object} any idea how i could alter this code to change have it return in the same format as the getCannedJson method?
getDataFromApiWithDynamicUrl this is no different than the above method but it will take a dyanmic url for the web api. It workds fine minus it not returning an array list of json objects it instead returns the same $$State object.
I would like getDataFromAPI to return the same array of all the objects in the json request like getCannedJson does. Any ideas where I am messing up. Below is a screenshot of the two different types of objects they are returning via console.log I would like the data at the bottom to look like the data at the top.
The code for the dataService module factory is below
(function (module) {
'use strict';
DataService.$inject = ['$http', '$q'];
function DataService($http, $q) {
var getDataFromAPI = function () {
var returnthis;
return $http({ //this top level returns instead
url: "http://localhost:34183/api/quality/month",
dataType: 'json',
method: 'GET',
}).success(function (response) {
console.log("This Response shown below is pefect! but it wont return....");
console.log(response);
return (response);//This never returns
}).error(function(error){
console.log(error);
});
return returnthis;
};
var getDataFromApiWithDynamicUrl = function (pathurl) { // this is version 2 of the method i want to work where i can dynamically change the url to the path
return $http.get(pathurl);
};
var getCannedJSON = function ($http) {
return [{
"hockeyTeam": "Sharks",
"PlayoffRecord": {
"wins": "0"
},
},
{
"hockeyTeam": "Pengiuns",
"PlayoffRecord": {
"wins": "1"
},
}
];
};
return {
getDataFromAPI: getDataFromAPI,
getDataFromApiWithDynamicUrl: getDataFromApiWithDynamicUrl,
getCannedJSON: getCannedJSON
};
}
module.factory('DataService', DataService);
})(angular.module('MyCoolModule'));
below is the code where i call these methods to consume the JSON data in my controller.
(function (module) {
'use strict';
hockeyViewController.$inject = ['DataService'];
function hockeyViewController(DataService) {
var vm = this;
vm.headers = [
{ name: 'Hockey Team', key: 'hockeyTeam' },
{ name: 'Record', key: 'PlayoffRecord'}
];
vm.cannedData = angular.copy(DataService.getCannedJSON());
vm.getDataFromAPI = DataService.getDataFromAPI();
vm.getDataFromAPIwithCustomURL = [];
DataService.getDataFromApiWithDynamicUrl("http://localhost:34183/api/quality/month").then(function(response){
console.log("this response should work - and it does it in the right format");
console.log(response.data);// this looks perfect
vm.getDataFromAPIwithCustomURL = response.data;
return response.data;
}, function (error) {
console.log(error);
});
vm.testMonthResults2 = angular.copy(DataService.getDataFromApiWithDynamicUrl("http://localhost:34183/api/quality/month"));
console.log("canned json Data- works great");
console.log(vm.cannedData);// this works perfectly
console.log("this is the data results with dynamic url - returns wrong object the $$state ");
console.log(vm.getDataFromAPI);// returns $$state not array of objects
console.log(vm.getDataFromAPIwithCustomURL); // this returns [] which is wrong
console.log(DataService.getDataFromApiWithDynamicUrl("http://localhost:34183/api/quality/month"));
// this doesnt work either
}
function reportTabularViewDirective() {
return {
restrict: "E",
controller: hockeyViewController,
controllerAs: 'vm',
bindToController: true,
scope: {
},
templateUrl: "app/widgets/hockey-view.html"
};
}
module.directive('hockeyView', hockeyViewDirective);
})(angular.module('MyCoolModule'));
Can try this one
var getDataFromAPI = function () {
return $http({
url: "/api/quality/month", // try using relative path
dataType: 'json',
method: 'GET',
}).then(function(response) {
console.log(response);
return respose.data;
}, function(error) {
console.log(error);
return [];
});
};
But better to use like: service return only promise and in controller use then function to handle response
In service:
var getDataFromAPI = function() {
return $http.get('/api/quality/month');
};
in controller:
DataService.getDataFromAPI().then(function(response) {
console.log(response.data);
}, function(error) {
console.log(error);
});
You get a $promise object by calling DataService.getDataFromAPI(). You need to handle the $promise object to get the response.
DataService.getDataFromAPI().then(function(response) {
// console.log(response);
})
The same applies when you getDataFromApiWithDynamicUrl() function.
For more info, see doc:
$http
$q

How to pass data from factory to controller in angular js?

I have one factory contains save customer function.On success I want to pass its response in controller so that i can update the view.
Factory
sampleApp.factory("authFactory", function($location, $http, transformRequestAsFormPost) {
return {
saveCustomer: function(data) {
var request = $http({
method: "post",
url: "webservice/ws.php?mode=saveCustomer",
transformRequest: transformRequestAsFormPost,
data: data
});
request.success(
function(response) {
console.log(response);
}
);
}
};
});
Controller
sampleApp.controller('customerController', function($scope, testService,authFactory,$http) {
$scope.addCustomer = function() {
var data = {name: $scope.customerName,city: $scope.customerCity};
// Calling Factory Function
authFactory.saveCustomer(data);
// How to fetch response here
}
});
Please help me to solve that problem
Thanks
Various ways, the first one that comes to mind is something like this:
//in your factory
return {
saveCustomer: function(data) {
var request = $http({...});
return request;
}
}
//in your controller
authFactor
.saveCustomer(data)
.success(function() {
//update controller here
})
You are working with "promises" here. You can do a few different things depending on what you return from your service method.
One thing you can do is simply return the promise and handle it in your controller.
service:
return {
saveCustomer: function(data) {
return $http({...});
}
}
contoller:
authFactor.saveCustomer(data).success(function(customer) {
$scope.customer = customer;
})
Another thing you can do is return an object reference and put it on your scope. When the object is filled, it will be updated in your scope.
service:
return {
saveCustomer: function(data) {
var customer = {};
$http({...}).success(function(data){
angular.copy(data, customer);
});
return customer;
}
}
controller:
$scope.customer = authFactor.saveCustomer(data);
The advantage of this second way is that most of your logic stays in your service. You controller stays simple and doesn't have to know about promises or handle them.

Not able to lazily update a controller scope with a REST service - Angularjs

I have basically created a cache in my Angular service. If the REST call has already been made, the an array is returned, else it makes the REST call to get the needed info. Here is my service:
define(function(require) {
var module = require('portal/js/services/app.services');
return module.factory('providerService', function($resource) {
return {
requestingProviders: [],
getRequestingProviders: function() {
var that = this;
if(this.requestingProviders.length === 0) {
this.getResource().search({
role: 'REQUESTING_PROVIDER'
}, function(data) {
that.requestingProviders = data.providers;
return that.requestingProviders;
});
} else {
return that.requestingProviders;
}
},
getResource: function() {
return $resource('/api/v1/providers/:providerId', {providerId:'#id'}, {
search: {
method: 'GET',
headers: {
'RemoteUser': 'jhornsby',
'Content-Type': 'application/json'
},
params: {
limit: 2000,
organizationId : '0001194'
}
}
});
}
};
};
Here is an example of me accessing the service from a controller:
define(function(require) {
var module = require('portal/js/controllers/app.controller');
module.controller('AddPatientCtrl', function($scope, providerService) {
$scope.providers = providerService.getRequestingProviders();
};
return module;
});
When the REST call returns, it does not update my scope.providers variable in my controller. When I try to access it a 2nd time, then it works fine by accessing the array instead of calling out to the REST service. WHy won't my scope update in my controller during the REST call?
The prpblem is that you are calling an async get method
You'll have to assign the $scope in a callback function from the service (or in this case the factory) to make sure that it will take the desired value.
As you have said, in the first time $scope is assined to something that has not been yet resolved but in subsequent calls that parameter is resolved so $scope will get the proper value.
I hope it helped.

angularjs $resource class-level callbacks, or post-processing

I have a $resource whose API will always return some data that needs to be cleaned up before going into the presentation layer. Specifically, it's .NET returning Date objects in the lovely '/Date(...)/' format.
I don't want to have to write a callback every time I call .query() or .get(). Is there some way to extend the resource with a callback that gets called upon REST methods that update the instance's properties, or by adding some sort of $watch that gets fired when the date property changes? Basically something that will happen for every instance of this $resource.
angular.module('myAppServices', ['ngResource'])
.factory('Participant', ['$resource', function ($resource) {
var res = $resource('api/url/participants/:id', { id: '#id' });
// This obviously doesn't work, but something kinda like this?
res.prototype.$watch(this.FieldName, function(newVal, oldVal) {
if (needsCleaning(newVal.fieldName) {
this.FieldName = cleanupField(newVal);
}
};
});
Ah-ha, I found a way around it and will leave it here. In version 1.1.2 they added support for passing all the $http.config options to a $resource. Naturally, the CDN I'm using doesn't have a recent enough version of angular-resource.js, but switching CDNs solved that.
I just used the transformResponse option to modify the data as it comes back.
angular.module('myAppServices', ['ngResource'])
.factory('Participant', ['$resource', '$http', function ($resource, $http) {
var res = $resource('api/url/participants/:id', { id: '#id' }, {
save: {
method: 'POST',
transformResponse: $http.defaults.transformResponse.concat([
function (data, headersGetter) {
data.FieldName = yourDateParsingFunction(data.FieldName);
return data;
}
])
}
});
I'm just adding my transformer on to $httpProvider's transformResponse, which will do all the deserialization, etc.
An easy way to do this is to overwrite the existing $resource methods you want to do post-processing on with your own. See the code and comments below for an example.
angular.module('myAppServices', ['ngResource'])
.factory('Participant', ['$resource', function ($resource) {
var res = $resource('api/url/participants/:id', { id: '#id' }, {
// create aliases for query and get to be used later
_query: { method: 'GET', isArray: true },
_get: { method: 'GET' }
});
// redefine the query method
res.query = function() {
// call the original query method via the _query alias, chaining $then to facilitate
// processing the data
res._query.apply(null, arguments).$then(function(res) {
var data = res.data;
// do any processing you need to do with data here
return data;
});
};
// redefine the method
res.get = function() {
// call the original get method via the _get alias, chaining $then to facilitate
// processing the data
res._get.apply(null, arguments).$then(function(res) {
var data = res.data;
// do any processing you need to do with data here
return data;
});
};
return res;
});
You'd use it the same way you're currently using Participant in your code, via Participant.query() or Participant.get(). The data you return in the chained $then handler will be used to resolve the promise returned by $resource.
The way I did it was by adding a service to the module:
angular.module('keeniolab', ['ngResource']).
factory('KeenIO',function ($resource) {
// factory implementation
}).service('KeenModel', function (KeenIO) {
var KeenSession = function () {
this.data = {};
};
KeenSession.prototype.fetch = function (query) {
var self = this;
KeenIO.get(query, function (result) {
self.data = result;
});
};
return new KeenSession();
});
Now you can simply monitor the collection:
$scope.$watchCollection(function () {
return KeenModel.data;
},
function (value) {
// code here
});
Keen.IO Resource Factory with Service Model

Categories