I have a factory that calls 4 json files and then I want to do some treatmenet for each data from these files and push them into an array of objects this is the code I wrote :
myapp.factory('wordsCloudFactory', function($http) {
var factory = {
getList: function() {
return $http.get('data/periode_1_file.JSON')
.then(function(response1) {
return $http.get('data/periode_2_file.JSON')
.then(function(response2) {
return $http.get('data/periode_3_file.JSON')
.then(function(response3) {
return $http.get('data/periode_4_file.JSON')
.then(function(response4) {
var words = [{
'period1': [],
'period2': [],
'period3': [],
'period4': []
}];
console.log(words);
for (var i = response1.data['X_id'].length - 1; i >= 0; i--) {
words['period1'].push({
id: response.data['X_id'][i],
count: response.data['count'][i]
});
};
for (var i = response2.data['X_id'].length - 1; i >= 0; i--) {
words['period2'].push({
id: response.data['X_id'][i],
count: response.data['count'][i]
});
};
for (var i = response3.data['X_id'].length - 1; i >= 0; i--) {
words['period3'].push({
id: response.data['X_id'][i],
count: response.data['count'][i]
});
};
for (var i = response4.data['X_id'].length - 1; i >= 0; i--) {
words['period4'].push({
id: response.data['X_id'][i],
count: response.data['count'][i]
});
};
return words;
}, function(error) {
return 'There was an error getting data';
})
}, function(error) {
return 'There was an error getting data';
})
}, function(error) {
return 'There was an error getting data';
})
}, function(error) {
return 'There was an error getting data';
})
}
};
return factory;
})
this code it doesnt work it shows me an error message : 'Cannot read property 'push' of undefined'.
How can I solve this ?
As you can see in my code there are a lot of nested $http.get methodes isn't there another way to write that ?
Your words is an array of object
var words = [{
'period1': [],
'period2': [],
'period3': [],
'period4': []
}];
You have to access it by index.
Try like this
words[0]['period1'].push({
id: response.data['X_id'][i],
count: response.data['count'][i]
});
JSFIDDLE
If it's just an object Like
var words = {
'period1': [],
'period2': [],
'period3': [],
'period4': []
};
Then your push was ok .
words['period1'].push({
id: response.data['X_id'][i],
count: response.data['count'][i]
});
JSFIDDLE
Related
I am trying to test this createParameterGroup function which is calling a private function, When I try to test this createParameterGroup function, it gives an error saying that validateParameterGroup is not a function.
controller
angular.module('PpmApp')
.controller('parameterGroupListController', ['$scope', '$injector', 'parameterGroups', parameterGroupListController]);
function parameterGroupListController($scope, $injector, parameterGroups) {
$scope.createParameterGroup = function (parameterGroup) {
var validationErrors = validateParameterGroup(parameterGroup);
if (validationErrors.isError) return;
parameterGroupApiService.createParameterGroup(parameterGroup);
}
function validateParameterGroup(parameterGroup) {
var validationErrors = {};
validationErrors.isError = false;
// Validations goes here
return validationErrors;
}
};
Test
describe('createParameterGroup', function() {
var validationErrors, parameterGroup;
beforeEach(function() {
validationErrors = {};
validationErrors.isError;
parameterGroup = {
GroupName: "ABC",
Description: "ABC",
fromMonth: 1,
fromYear: 18,
toMonth: 12,
toYear: 18
}
});
it('should create a parameter group', function() {
expect($scope.createParameterGroup(parameterGroup)).toEqual(false);
});
});
After spending some time around how to write test cases right, I figured it out that I was doing expecting the wrong condition to evaluate the correct output. So this is how I have done it now.
Test Cases
describe('createParameterGroup', function() {
it('with blank name returns error message of property name can not be blank', function() {
var parameterGroup = {
name: "",
description: "sss",
fromMonth: 1,
fromYear: 18,
toMonth: 12,
toYear: 18
};
$scope.createParameterGroup(parameterGroup);
for (var property in parameterGroup) {
if (!parameterGroup[property] && property != 'description') {
var propertyName = (property == 'name') ? 'Parameter group name' : property;
}
return property;
}
expect($scope.createPopupInfo.validationErrors.isError).toEqual(true);
expect($scope.createPopupInfo.validationErrors[property]).toEqual(propertyName + ' ' + constantsProvider.validationMessages.blankField);
});
it('with special characters returns error message of invalid parameter group name', function() {
var parameterGroup = {
name: "/*&",
description: "ABC",
fromMonth: 1,
fromYear: 18,
toMonth: 12,
toYear: 18
};
$scope.createParameterGroup(parameterGroup);
expect($scope.createPopupInfo.validationErrors.isError).toEqual(true);
expect($scope.createPopupInfo.validationErrors.name).toEqual('Parameter group name \'' + parameterGroup.name + '\' ' + constantsProvider.validationMessages.specialCharacters);
});
it('with invalid effective time period returns error message of Invalid effective time period', function() {
var parameterGroup = {
name: "ABC",
description: "ABC",
fromMonth: 5,
fromYear: 18,
toMonth: 4,
toYear: 18
};
$scope.createParameterGroup(parameterGroup);
expect($scope.createPopupInfo.validationErrors.isError).toEqual(true);
expect($scope.createPopupInfo.validationErrors.toYear).toEqual(constantsProvider.validationMessages.effectiveTimePeriod);
});
it('with valid input returns the given input back without any error message', function() {
var parameterGroup = {
GroupName: "ABC",
Description: "sss",
EffectiveStartDateTime: 1 / 18,
EffectiveEndDateTime: 12 / 18
};
var createResponse = {};
createResponse.IsSuccess = true;
spyOn(parameterGroupApiService, 'createParameterGroup').and.callFake(function() {
return {
then: function(callback) {
return callback(createResponse);
}
}
});
spyOn(parameterGroupApiService, 'getParameterGroups').and.callFake(function() {
return {
then: function(callback) {
callback(parameterGroup);
return {
catch: function() {}
}
}
}
});
$scope.createParameterGroup(parameterGroup);
expect($scope.createPopupInfo.validationErrors.isError).toEqual(false);
expect(parameterGroupApiService.createParameterGroup).toHaveBeenCalled();
expect(parameterGroupApiService.getParameterGroups).toHaveBeenCalled();
expect($scope.parameterGroups).toBe(parameterGroup);
});
});
The below code is working for me to get data on API calls but I have one question here. Every time it creates elements in DOM and populate the data which we get from API. But if I get lesser records it is showing blank/empty records. How can I remove or stop generating those blank records?
this.infiniteItems = {
numLoaded_: 0,
toLoad_: 0,
items: [],
getItemAtIndex: function (index) {
if (index > this.numLoaded_) {
this.fetchMoreItems_(index);
return null;
}
return this.items[index];
},
getLength: function() {
return this.numLoaded_ + 25;
},
fetchMoreItems_: function (index) {
if (this.toLoad_ < index) {
this.toLoad_ += 5;
var offset = 0;
$http({
method: 'GET',
datatype: 'json',
url: '{my-api-call}',
contentType: "application/json; charset=utf-8",
cache: false,
params: {
param: query,
page: offset
}
}).then(angular.bind(this, function (obj) {
this.items = this.items.concat(obj.data.SearchResults);
this.numLoaded_ = this.toLoad_;
this.offset++;
$scope.searchResults = obj.data.SearchResults;
}));
}
}
};
Thanks in advance.
I had the same problem and I solved it like this:
$scope.infiniteBrands = {
numLoaded_: 0,
toLoad_: 0,
items: [],
page: -1,
hasMoreItems: true,
perPage: 7,
//REQUIRED.
getItemAtIndex: function(index) {
if (index > this.numLoaded_) {
this.fetchMoreItems_(index);
return null;
}
return this.items[index];
},
//REQUIRED
getLength: function() {
return this.numLoaded_ + 1;
},
fetchMoreItems_: function(index) {
if ( this.hasMoreItems && (this.toLoad_ < index)) {
this.page++;
this.toLoad_ += this.perPage;
brandsFactory.getBrands(this.perPage, this.page)
.then(angular.bind(this, function (data) {
this.items = this.items.concat(data);
if(data.length < this.perPage){
this.numLoaded_ = this.toLoad_ - (this.perPage - data.length) -1;
this.hasMoreItems = false;
}else{
this.numLoaded_ = this.toLoad_;
}
}))
.catch(function(errorResponse){
console.log('Error in brands controller, status : ', errorResponse.status);
});
}
}
};
As you can see the lines that prevents the empty rows are:
if(data.length < this.perPage){
this.numLoaded_ = this.toLoad_ - (this.perPage - data.length) -1;
this.hasMoreItems = false;
}else{
this.numLoaded_ = this.toLoad_;
}
where this.perPage are the number of items I want to ask per page but if the server returns me a lower number, because there are no more, I need to substract those from the this.numLoaded_ variable.
Its late but I hope it helps to anyone who had the same problem.
You should check if your API call has reached the lastPage.
fetchMoreItems_: function (index) {
if ((this.toLoad_ < index) && !this.lastPage) {
this.toLoad_ += this.size;
newsActions.getNews(this.page++, this.size).then(angular.bind(this, function (newsData) {
this.items = this.items.concat(newsData.content);
this.numLoaded_ = this.toLoad_ >= newsData.totalElements ? newsData.totalElements : this.toLoad_ ;
this.lastPage = newsData.last;
}));
}
}
Then use it in getLength function:
getLength: function () {
if(this.lastPage){
return this.numLoaded_
}
return this.numLoaded_ + 2;
},
$scope.form={
Name:"",
fields:[
{
id:"",
Name:"",
type:"dfsd",
order:""
}
]
};
How to access the type value in the above object.I need to push the value into it..i could not able to do..so first i thought to retrieve once I could not do..So can i have a solution for both the operations.Push and retrieve the value .
use this code:::
$scope.savebutton = function() {
angular.forEach($scope.textboxes, function(text) {
if (text != undefined && text.length != 0) {
inputs = [];
angular.forEach($scope.textboxes, function(t) {
inputs.push(t);
});
}
});
var textfield = {
id: "1",
Name: "textbox"
}
$scope.form = {};
$scope.form.fields = [];
$scope.form.fields.push(textfield);
console.log(angular.toJson($scope.form));
ngDialog.closeAll();
};
I have a factory defined like this:
mob.factory("OrderHelper", function() {
return {
lineItemPrice: function(lineItem) {
return lineItem.price * lineItem.quantity;
},
orderTotal: function(order) {
order.items.forEach(function (item)) {
total += lineItemPrice(item);
}
}
}
});
That problem is that I can't use the method "lineItemPrice" in "orderTotal" method.
It throws this error: Error: [$interpolate:interr] Can't interpolate: £{{orderTotal(order)}}
Can somebody please tell how can I call a method from a function in the same factory.
Thanks.
you could also do it like this:
mob.factory("OrderHelper", function() {
var methods = {};
methods.lineItemPrice = function(lineItem) {
return lineItem.price * lineItem.quantity;
};
methods.orderTotal = function(order) {
order.items.forEach(function (item)) {
total += methods.lineItemPrice(item);
}
};
return methods;
});
Try this (the revealing module pattern):
mob.factory("OrderHelper", function() {
var lineItemPrice = function(lineItem) {
return lineItem.price * lineItem.quantity;
};
var orderTotal = function(order) {
order.items.forEach(function (item)) {
total += lineItemPrice(item);
}
};
return {
lineItemPrice: lineItemPrice,
orderTotal: orderTotal
}
});
You can use angular.foreach() to iterate each items and supply the third parameter as the context of the callback function.
mob.factory("OrderHelper", function() {
return {
lineItemPrice: function(lineItem) {
return lineItem.price * lineItem.quantity;
},
orderTotal: function(order) {
var total = 0;
angular.forEach(order.items, function(item) {
total += this.lineItemPrice(item)
}, this); // add `this` as the context of the callback
return total;
}
}
});
I have an issue with loading remote data in multiple select2. My code is
var fetchGroups = function (queryParams) {
console.log(JSON.stringify(queryParams));
return $http.get("https://******/****/***/" + queryParams.data.query).then(queryParams.success);
};
$scope.groupSelectOptions= {
minimumInputLength: 3,
ajax: {
data: function (term, page) {
return { query: term };
},
quietMillis: 500,
transport: fetchGroups,
results: function (data, page) {
console.log(data);
// parse the results into the format expected by Select2 return { results: data };
var drastics = data.data.result;
if(drastics){
var data = new Array();
for(var i = 0; i < drastics.length; i++){
data.push(
{
id: drastics[i].id,
text: drastics[i].name
}
);
}
} else {
data = data.data.result;
}
return { results: data };
}
}
};
It returns the values from the get request but when i select it returns undefined at the input box.
Just make sure you've included the 'data' property to the $scope.groupSelectOptions like so :
$scope.groupSelectOptions= {
minimumInputLength: 3,
ajax: {
data: function (term, page) {
return { query: term };
},
.....
data:[]}
You should now see the term selected in the input field.