why do I get ..is not a function? - angularjs

I am trying to create an angular service but getting an error. This is the service:
var app = angular.module('plunker', []);
// Filter Service that returns records with crdamt positive:
app.factory('FilterService', function() {
return function(d) {
var filteredData = [];
console.log(d);
d.forEach(function(item)
{
if (item.cramt > 0) {
filteredData.push(item);
}
});
return filteredData;
}
});
In my unit test however we get:
it('should return transactions where credit is positive', function() {
var jsonData = {
"transactions": [{
"date": "1/1/2000",
"desc": "Purchase",
"cramt": 50,
"dbamt": 0
}, {
"date": "1/1/2002",
"desc": "Transaction",
"cramt": 110,
"dbamt": 10
}]
};
var filteredRecords = FilterService(jsonData);
expect(filteredRecords).toEqual({
"date": "1/1/2000",
"desc": "Purchase",
"cramt": 50,
"dbamt": 0
});
});
Why do I get an error:
TypeError: d.forEach is not a function
plunkr:http://plnkr.co/edit/jdg0wEj1zSDTbqojBAoc?p=preview

forEach method is available on arrays.
Looking at your jsonData you can do this:
app.factory('FilterService', function() {
return function(data) {
var filteredData = [];
console.log(data.transactions);
data.transactions.forEach(function(item)
{
if (item.cramt > 0) {
filteredData.push(item);
}
});
return filteredData;
}
});
P.S: Please read the error messages. It clearly says that d.forEach is not a functions. It is like trying to define an object like:
var person = {
'name':'Paul'
};
and trying to access person.height(). The height is not a property of person object and you are trying to access undefined property as a function.
More info

Just try. I'm expecting variable d as an array.
angular.forEach(d, function(item){
if (item.cramt > 0) {
filteredData.push(item);
}
});
You're not using the right syntax for forEach function of angular js. Please refer this angular.forEach directive

Your test is trying to filter the entire object instead of the array of transactions.
var filteredRecords = FilterService(jsonData);
expect(filteredRecords).toEqual({
"date": "1/1/2000",
"desc": "Purchase",
"cramt": 50,
"dbamt": 0
});
should be
var filteredRecords = FilterService(jsonData.transactions);
expect(filteredRecords).toEqual([{
"date": "1/1/2000",
"desc": "Purchase",
"cramt": 50,
"dbamt": 0
}]);

Please look at the updated plnkr. forEach is used for the arrays only and your 'd' returns an object.
Following is the link to the plnkr :
``http://plnkr.co/edit/o65e0xEsBiW0jpawhGse?p=preview

you can define filter in this way.
app.factory('FilterService', function() {
return function(d) {
var filteredData = [];
var boolDataISFound = false;
console.log(d.transactions)
d.transactions.forEach(function(item,index)
{
if (item.cramt > 0) {
filteredData.push(item);
}
});
return filteredData[0];
}
});
and here is the expectation
it('should return transactions where credit is positive', function() {
var jsonData = [{
"transactions": [{
"date": "1/1/2000",
"desc": "Purchase",
"cramt": 50,
"dbamt": 0
}, {
"date": "1/1/2002",
"desc": "Transaction",
"cramt": 110,
"dbamt": 10
}]
}];
var filteredRecords = FilterService(jsonData[0]);
expect(filteredRecords).toEqual({
"date": "1/1/2000",
"desc": "Purchase",
"cramt": 50,
"dbamt": 0
} );
});
Here is the Plunker

Related

Angular JS : How to create a Array dynamically by reading a JSON Array

I have a JSON as below
[
{
"id": 1000,
"name": "Open"
},
{
"id": 1000,
"name": "Ravi"
},
{
"id": 1000,
"name": "POOO"
}]
On click of a button I am trying to create a Array by reading all the names from the Array
I have tried as follwoing
var myapp = angular.module('myapp', []);
myapp.controller('FirstCtrl', function($scope)
{
$scope.formData = function()
{
var aa = $scope.tickets.length;
$scope.products = $scope.tickets.name;
alert($scope.products);
};
$scope.tickets = [
{
"id": 1000,
"name": "Open"
},
{
"id": 1000,
"name": "Ravi"
},
{
"id": 1000,
"name": "POOO"
}]
});
Currently i am getting undefined , could you please let me know how to do this
Thanks in advance
http://jsfiddle.net/9fR23/434/
I dont want tradional style using a for loop to read .
Could you please suggest a professional approach .
If you won't to use a loop to read, then you can use Underscore.js.
By using Underscore.js you can do this as below. before that you need to check this link for how use underscore inside angular controllers.
var result = _.map([{ id: 1, name: "vinit"},{ id: 2, name: "jaimin"}], function (v) {
return v.name;
});
alert(JSON.stringify(result));
jsfilddle
You can make a loop to read all data in array and push them to your new array:
$scope.formData = function()
{
$scope.products = [];
var aa = $scope.tickets.length;
angular.forEach($scope.tickets, function(value, key) {
$scope.products.push(value.name);
});
alert($scope.products);
};
Updated fiddle

JSON conversion issue when returning data from Firebase using angular

I am retrieving data from Firebase and when I convert to JSON like this:
$scope.array.push(angular.toJson(obj));
I get this:
["{ "lat": "50", "lon": "3", "title": "my title", "content": "my content" }"]
How do I convert it so that I get this:
[{ "lat": "50", "lon": "3", "title": "my title", "content": "my content"}]
In my angular directive I see the data when I console.log it and it appears like this:
[]
0: "{ "lat": "50", "lon": "3", "title": "my title", "content": "my content" }"
In order to get the data from Firebase, if I do $scope.array.push(obj); I get this:
[]
0 {key : "value"}
So in order to get my code to run I need the 'key' in quotes too.
The other issue I'm having is that the link function in my directive is running before the data is returned in the scope.arrLocations variable. There is a watch that I expected to pick up changes to this variable. So I was expecting that when I got the data formatted properly it would just work.
Here's my code in full:
app.factory('map', ['$q', function($q){
var map={};
var mapInfoItems=[];
map.getMapInfo = function() {
var deferred = $q.defer();
var mapitems = firebase.database().ref('mapinfo/'+firebase.auth().currentUser.uid);
mapitems.on('child_added', function(snapshot){
mapInfoItems.push(snapshot.val());
deferred.resolve(mapInfoItems);
});
//return mapInfoItems;
return deferred.promise;
};
return map;
}]);
app.controller('mapController', ['$scope', 'map', function($scope, map){
$scope.myLocations = {};
$scope.arrLocations = [];
var allLocations = [];
//$scope.arrLocations = [ { "lat": "50", "lon": "3", "title": "my title", "content": "my content" }];
$scope.mapLocations = map.getMapInfo();
map.getMapInfo().then(function(locations){
for(var i=0; i<locations.length; i++){
// create new object each iteration
var obj ={
title : locations[i].name,
content: locations[i].message,
lat : locations[i].lat,
lon : locations[i].lon
}
allLocations.push(obj);
}
$scope.arrLocations = allLocations;
});
}]);
app.directive('myMap', [function() {
// directive link function
var link = function(scope, element, attrs) {
//console.log(scope.myLocations);
console.log('in the link function');
//the line below works and the marker is shown on the map
//scope.arrLocations = [ { "lat": "50", "lon": "3", "title": "my title", "content": "my content" }];
//console.log(scope.arrLocations);
var map, infoWindow;
var markers = [];
//var lastElement = '';
// map config
var mapOptions = {
// center: new google.maps.LatLng(50, 3),
center: new google.maps.LatLng(scope.lastElement.lat, scope.lastElement.lon),
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP,
scrollwheel: true
};
// init the map
function initMap() {
if (map === void 0) {
map = new google.maps.Map(element[0], mapOptions);
}
}
// place a marker
function setMarker(map, position, title, content) {
var marker;
var markerOptions = {
position: position,
map: map,
title: title,
icon: 'https://maps.google.com/mapfiles/ms/icons/green-dot.png'
};
marker = new google.maps.Marker(markerOptions);
markers.push(marker); // add marker to array
google.maps.event.addListener(marker, 'click', function () {
// close window if not undefined
if (infoWindow !== void 0) {
infoWindow.close();
}
// create new window
var infoWindowOptions = {
content: content
};
infoWindow = new google.maps.InfoWindow(infoWindowOptions);
infoWindow.open(map, marker);
});
}
scope.$watch(function() { return scope.arrLocations; }, function() {
initMap();
console.log(scope.arrLocations);
scope.lastElement = scope.arrLocations[scope.arrLocations.length - 1];
// clear markers
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
markers = [];
angular.forEach(scope.arrLocations, function(value, key){
//console.log('value: ' + value + ' | key: ' + key);
// a single object in this example could be:
// { lat: 50, lon: 3, title: "my title", content: "my content" }
var location = new google.maps.LatLng(value.lat, value.lon);
setMarker(map, location, value.title, value.content);
});
});
};
return {
restrict: 'EA',
//scope: {getMapFn: '&'},
template: '<div id="gmaps"></div>',
replace: true,
link: link
};
}]);
Don't stringify the object...just push the object itself to array
Change:
$scope.array.push(angular.toJson(obj));
To
$scope.array.push(obj);
As for the console log of length it sounds like you are trying to check length before data has been pushed into the array. Most likely before the data request has been received
Gave up using my existing code. Decided to use this instead.

angular service test fails to return required response

I am trying to write tests for angular service using jasmine and karma. I have the following code for my service call:
angular.module('omdb', [])
.factory('myservice', MyService);
MyService.$inject = ['$http'];
function MyService($http) {
var vm = this;
var service = {};
service.getData = function() {
return $http.get('omdb/mydata.json').then(function(response) {
return response.data;
});
};
return service;
};
I am tesitng it using the following file for spec as:
describe('myservice', function() {
var mockservicedata = [{
"name": "value1",
"id": "1"
}, {
"name": "value2",
"id": "2"
}, {
"name": "value3",
"id": "3"
}];
var myservice = {};
beforeEach(module('omdb'));
beforeEach(inject(function(_myservice_) {
myservice = _myservice_;
}));
it('should return search myservice data', function() {
expect(myservice.getData()).toEqual(mockservicedata);
});
});
which basically throws an error as:
Expected d({ $$state: Object({ status: 0 }) }) to equal [ Object({ name: 'value1', id: '1' }), Object({ name: 'value2', id: '2' }), Object({ name: 'value3', id: '3' }) ].
stack#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1482:17
buildExpectationResult#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1452:14
Env/expectationResultFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:583:18
Spec.prototype.addExpectationResult#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:324:29 addExpectationResult#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:533:16
Expectation.prototype.wrapCompare/<#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1406:7
#http://localhost:59239/movie-app/spec/omdb/myservice.spec.js:14:9
attemptSync#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1789:9
QueueRunner.prototype.run#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1777:9 QueueRunner.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1762:5
Env/queueRunnerFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:627:7
Spec.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:353:5 executeNode/<.fn#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:2360:32 attemptAsync#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1819:9
QueueRunner.prototype.run#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1774:9
QueueRunner.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1762:5
Env/queueRunnerFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:627:7
executeNode/<.fn#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:2345:13 attemptAsync#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1819:9
QueueRunner.prototype.run#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1774:9
QueueRunner.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1762:5
Env/queueRunnerFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:627:7
TreeProcessor/this.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:2209:7
Env/this.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:678:7
window.onload#http://localhost:59239/movie-app/lib/jasmine-2.3.4/boot.js:110:5
I don't understand why it does not return data to the test. please help
Calling myservice.getData() won't actually give you the data you're expecting.
Since your getData method from MyService relies on $http's get method, you should be mocking it and then expecting that data returned.
So your test case should be like:
describe('myservice', function() {
var mockservicedata = [{
"name": "value1",
"id": "1"
}, {
"name": "value2",
"id": "2"
}, {
"name": "value3",
"id": "3"
}];
var myservice = {};
beforeEach(module('omdb'));
beforeEach(inject(function(_myservice_, _$httpBackend_) {
myservice = _myservice_;
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', "omdb/mydata.json").respond({
status: 200,
data: mockservicedata
});
}));
it('should return search myservice data', function() {
var response = myservice.getData()
response.then(function(response) {
expect(response.data).toEqual(mockservicedata);
});
$httpBackend.flush();
});
});
Hope this helps.
getData() will never return data instead it will return promise object.
If you want to test it then firstly you would have to mock the data for service then you can call it and match the result in the success handler.
Code is attached below:
describe('myservice', function() {
var mockservicedata = [{
"name": "value1",
"id": "1"
}, {
"name": "value2",
"id": "2"
}, {
"name": "value3",
"id": "3"
}];
var myservice, httpBackend;
beforeEach(module('omdb'));
beforeEach(inject(function(_myservice_, $httpBackend) {
myservice = _myservice_;
httpBackend = $httpBackend;
}));
it('should return search myservice data', function() {
httpBackend.when("GET", "omdb/mydata.json").respond(mockservicedata);
var promise = myservice.getData();
promise.then(function(response) {
expect(response.data).toEqual(mockservicedata);
});
httpBackend.flush();
});
});

How to push named Json Array Into Json Object

I want to push below data. I want order the items, it consists of following fields:
var OrderItem = {"itemid":item.itemid,"itemname":item.itemname,"qty":1,"itemprice":item.itemprice};
But I want to Store Like this
{
"Items": [
{
"itemid": 50,
"itemname": "sample",
"itemprice": 124,
"qty": 1
},
{
"itemid": 52,
"itemname": "sample",
"itemprice": 124,
"qty": 1
}
]
}
Controllers:
$scope.addnew=function(item){
var OrderItem= {"itemid":item.itemid,"itemname":item.itemname,"qty":1,"itemprice":item.itemprice};
NewOrderService.addOrderitems(OrderItem);
}
}
Services:
servctrl.service("NewOrderService", function(NewOrderFactory) {
this.addOrderitems = function(orderitemnew) {
NewOrderFactory.AddOrdernew(orderitemnew);
}
});
Factorys:
factmodule.factory("NewOrderFactory",function(){
var orderitemsnew=[];
return {
AddOrdernew:function(orderitemnew){
orderitemsnew.push(orderitemnew);
}
}
});
How to Achieve this?
probably like this?
factmodule.factory("NewOrderFactory",function(){
var orderitemsnew={
items = [];
};
return{
AddOrdernew:function(orderitemnew){
orderitemsnew.items.push(orderitemnew);
},
getOrderItemsNewList: function() {
return orderitemsnew;
}
};
});

Underscore JS to retrieve object by ID

I have a input where I want to find an object by ID. At the moment I am returning both objects but what I want is if I search '01' I would just return the first object. I have tried underscore _.map to do this but it did not give the result I am after.
var getById = function() {
var deferred = Q.defer(),
result;
result = items;
if (!result) {
deferred.reject('item not found');
} else {
deferred.resolve(result);
}
return deferred.promise;
};
JSON:
[{
"id": "01",
"name": "test1",
"orderItems": [
{
"productNumber": "TESTa",
"quantity": 2,
},
{
"productNumber": "TESTb",
"quantity": 4,
},
{
"productNumber": "TESTc",
"quantity": 6,
}
]
},{
"id": "02",
"name": "test2",
"orderItems": [
{
"productNumber": "TESTe",
"quantity": 2,
},
{
"productNumber": "TESTf",
"quantity": 7,
},
{
"productNumber": "TESTg",
"quantity": 6,
}
]
}]
You can use _.filter()
Looks through each value in the list, returning an array of all the values that pass a truth test (predicate).
result = _.filter(items, function(item){
return item.id == '01';
});
Or, _.findWhere
Looks through the list and returns the first value that matches all of the key-value pairs listed in properties.
result = _.findWhere(items, {id : '01'});
var result = _.find(myItems, function(item) { return item.id === '01'; }
If you find single item which matches the conditions, use _.find()
It looks through each value in the list, returning the first one that
passes a truth test
var _exist = _.find(_items, function (item) {
return item.id == your_id;
});
If you find all items which matches the conditions, use _.filter()
It looks through each value in the list, returning an array of all the
values that pass a truth test
var _exist = _.filter(_items, function (item) {
return item.id == your_id;
});
Catch the complete documentation here:
http://underscorejs.org/

Resources