Changing the text of an element when referencing it from an array - angularjs

I'm trying to change text elements in a page based on numerical values I pass back from my server. I manage to store each reference as well as the value from the server, but when trying to access to the text value of the object I get hit with the error statusText[key].text is not a function. is it possible to access the object properties when referencing from a list? Javascript and Angular are not my strong suits.
Here's the code:
var log = [];
var statusText = [];
$http.post("url", {userid: currentUserID})
.then(function(response)
{
angular.forEach(response.data.status, function(value, key){
this.push(value.complete);
}, log);
angular.forEach(document.getElementsByClassName("step-status"), function(value, key)
{
this.push(value)
}, statusText);
angular.forEach(statusText, function(value, key)
{
if (log[key] == 2)
{
statusText[key].text('Completed');
}
else if (log[key] == 1)
{
statusText[key].text('In progress');
}
else
{
statusText[key].text('Not started');
}
});
});

Try this
var log = [];
var statusText = [];
$http.post("url", {userid: currentUserID})
.then(function(response)
{
angular.forEach(response.data.status, function(value, key){
this.push(value.complete);
}, log);
angular.forEach(document.getElementsByClassName("step-status"), function(value, key)
{
this.push(value)
}, statusText);
angular.forEach(statusText, function(value, key)
{
if (log[key] === 2)
{
statusText[key] = 'Completed';
}
else if (log[key] === 1)
{
statusText[key] = 'In progress';
}
else
{
statusText[key] = 'Not started';
}
});
});

Sollution: Changed my approach for displaying the returned strings. Just set each element of the array to the string I want and used bindings to display the data.
Thanks for the help all.

Related

How to push a JSON object to an array in AngularJS

I need to push a JSON object to AngularJS and need to check before if the value for one of the objects exist. I need to overwrite the data.
$scope.setData = function(survey, choice) {
keepAllData.push({
'surveyId': survey.id,
'choiceId': choice.id
});
console.log(keepAllData);
toArray(keepAllData);
alert(JSON.stringify(toArray(keepAllData)));
$scope.keepAllDatas.push({
'surveyId': survey.id,
'choiceId': choice.id
});
var items = ($filter('filter')(keepAllDatas, {
surveyId: survey.id
}));
}
function toArray(obj) {
var result = [];
for (var prop in obj) {
var value = obj[prop];
console.log(prop);
if (typeof value === 'object') {
result.push(toArray(value));
console.log(result);
} else {
result.push(value);
console.log(result);
}
}
return result;
}
If the survey id exists in keepalldata, I need to change the recent value with choiceid. Is it possible to do with AngularJS?
Try with this: Before pushing data you have to check if the survey id exists or not. If it exists you have to update choice with the corresponding survey id, otherwise you can push directly.
$scope.setData = function(survey, choice) {
var item = $filter('filter')(keepAllData, {
surveyId: survey.id
});
if (!item.length) {
keepAllData.push({
'surveyId': survey.id,
'choiceId': choice.id
});
} else {
item[0].choiceId = choice.id;
}
console.log(keepAllData);
}
Demo
$scope.keepAllDatas = [];
$scope.setData = function(survey, choice) {
if($scope.keepAllDatas.length == 0) {
$scope.keepAllDatas.push({'surveyId':survey.id,'choiceId':choice.id});
}
else {
var items = ($filter('filter')( $scope.keepAllDatas, {surveyId: survey.id }));
for (var i = items.length - 1; i >= 0; i--) {
// alert(items[i].surveyId);
if(items[i].surveyId == survey.id) {
console.log($scope.keepAllDatas.indexOf(survey.id));
$scope.keepAllDatas.splice($scope.keepAllDatas.indexOf(survey.id),1);
console.log("Removed data")
}
}
$scope.keepAllDatas.push({'surveyId':survey.id, 'choiceId':choice.id});
console.log( $scope.keepAllDatas)
// alert(items[0].surveyId);
}
}

Issue with handling two responses from two different ajax calls

I have an issue in my module i am mapping two responses(arrays) from two different ajax calls,so that i got a total response of two ajax calls as single array.Here I have to use that total response out of the angular for each loop to post some of the properties.But due to for each loops the object is posted repeatedly.
Here is my code:
$scope.fnGetDetails = function(uniqueId) {
$scope.uniqueId = uniqueId.jdDetails.uniqueId;
angular.forEach($scope.aIdResponse, function(value, key) {
console.log(value.jdDetails.uniqueId);
if (value.jdDetails.uniqueId == $scope.uniqueId) {
$scope.jdList = value.recruiter;
}
});
$scope.aRecPush = [];
$scope.aSelectedPush = [];
angular.forEach($scope.jdList, function(value, key) {
interviewStatusService.fnGetRecruiterDetails($scope.uniqueId, value).then(function(response) {
$scope.recResponse = response;
if ($scope.aRecPush.indexOf($scope.recResponse) === -1) {
$scope.aRecPush.push($scope.recResponse);
}
$scope.aRecVar = $scope.aRecPush;
});
interviewStatusService.fnGetSelectedProfiles($scope.uniqueId, value).then(function(response) {
$scope.aRes = response;
$scope.aLength = $scope.aRes.length;
if ($scope.aSelectedPush.indexOf($scope.aLength) === -1) {
$scope.aSelectedPush.push($scope.aLength);
$scope.aSelectedVar = $scope.aSelectedPush;
$scope.mappedData = $scope.aRecVar.map(function(value, index) {
return {
data: value,
value: $scope.aSelectedVar[index]
}
});
}
angular.forEach($scope.mappedData, function(value, key) {
interviewStatusService.fnPostRecruiterTrack(value.data[0].recruiter, value.data[0].length, value.data[0].uniqueId, value.value).then(function(response) {
console.log(response);
})
});
});
});
Any help would be appreciated.

Ag-Grid - Saving columns for future use

I am using the ag-grid for angular1, (and loving it), and I want my users to be able to reorgenize columns, change sortings, and everything, and that it will stay after a refresh.
It should not be very hard, except that the columns are circular (contains pointers to themselves), and thus I cannot parse them.
Code:
var columnDefsKey = "columnDefs["+$rootScope.page+"]";
var savedColumns = localStorage.getItem(columnDefsKey);
function saveColumnsState() {
var currentCol = vm.gridOptions.columnApi.getAllColumns();
if (!angular.equals(currentCol, savedColumns))
try {
localStorage.setItem(columnDefsKey, JSON.stringify(currentCol));
} catch (ex) {
log(ex);
log(currentCol);
}
}
And:
onColumnEverythingChanged: saveColumnsState,
onColumnVisible: saveColumnsState,
onColumnPinned: saveColumnsState,
onColumnResized: saveColumnsState,
onColumnRowGroupChanged: saveColumnsState,
onColumnValueChanged: saveColumnsState,
onColumnMoved: saveColumnsState,
onColumnGroupOpened: saveColumnsState,
It fails on the "try" every time:
TypeError: Converting circular structure to JSON(…) [Column, Column, Column, Column, Column, Column, Column, Column, Column, Column]
How can I do that? (save columns for later use)
If I manage to do that, I will be able to create several views without coding.
you can get the better understanding of the issue from below link
Chrome sendrequest error: TypeError: Converting circular structure to JSON
Also check below reference
https://github.com/isaacs/json-stringify-safe
The way to achieve this was to build my own column model, that I can save and parse again, and in which to save only necessary properties.
This method is XSS vulnerable, as I am evaluating functions, but it is a working solution.
columnsApi: {
key: null,
grid: null,
newColumnModel: {
headerName: "",
width: 200,
valueGetter: "",
filter: 'text',
aggFunc: 'none',
filterParams: {apply: true}
},
setKey: function (key) {
this.key = key;
},
setGrid: function (grid) {
this.grid = grid;
},
format: function (columns) {
var format = [];
angular.forEach(columns, function (col) {
var colDef = {
width: col.actualWidth,
pinned: col.pinned,
hide: !col.visible
};
format.push(angular.extend(col.colDef, colDef));
});
return format;
},
getIDs: function (columns) {
var ids = [];
angular.forEach(columns, function (col) {
ids.push(col.colId);
});
return ids;
},
stringify: function (columns) {
return JSON.stringify(columns, function (key, value) {
if (typeof value === "function")
return "/Function(" + value.toString() + ")/";
return value;
});
},
parse: function (string) {
return JSON.parse(string, function (key, value) {
if (typeof value === "string" &&
value.startsWith("/Function(") &&
value.endsWith(")/")) {
value = value.substring(10, value.length - 2);
return eval("(" + value + ")");
}
return value;
});
},
add: function (column) {
if (this.grid === null) {
console.error("Assertion error: grid must not be null");
return;
}
if(column.aggFunc == 'none')
column.aggFunc = undefined;
var groups = this.get().groups;
var newColumns = this.format(getGridColumns(this.grid));
newColumns.push(column);
this.grid.api.setColumnDefs(newColumns);
this.setGroups(groups);
},
save: function () {
var self = this;
if (this.key === null) {
console.error("Assertion error: key must not be null");
return;
}
if (this.grid === null) {
console.error("Assertion error: grid must not be null");
return;
}
var savedOptions = {
columns: self.format(getGridColumns(self.grid)),
groups: self.getIDs(self.grid.columnApi.getRowGroupColumns()),
sorting: self.grid.api.getSortModel(),
filter: self.grid.api.getFilterModel()
};
localStorage.setItem(this.key, this.stringify(savedOptions));
},
// Get function uses "eval" - XSS vulnerable.
get: function () {
if (this.key === null) {
console.error("Assertion error: key must not be null");
return;
}
var options = localStorage.getItem(this.key);
if (options)
options = this.parse(options);
return options;
},
remove: function (field) {
if (this.grid === null) {
console.error("Assertion error: grid must not be null");
return;
}
var newColumns = this.format(getGridColumns(this.grid));
angular.forEach(newColumns, function (col, key) {
if (col.field == field)
newColumns.splice(key, 1);
});
this.grid.api.setColumnDefs(newColumns);
},
setGroups: function (groups) {
var self = this;
angular.forEach(groups, function (id) {
angular.forEach(getGridColumns(self.grid), function (col) {
if (col.colId == id)
self.grid.columnApi.addRowGroupColumn(col);
});
});
}
}
This solution was written for Ag-Grid 5 I believe, and thus I am not sure if it still holds.

Angular JS Promise - Binding inside a forEach loop

I am using angular.forEach to iterate over an array and for each value in the array, I am using a GET/ to retrieve it's name (array contains key), then push that name into another array. This new array is being used in a dropdown box (ngOptions).
The issue I am having is that the drop down is being created before the GET/ responses have arrived, so it just displays blank options, then when they arrive it displays all options in each drop down.
I have the following code:
angular.forEach($scope.pots, function(value, key) {
$scope.selections = [];
angular.forEach(value, function(val, ky) {
if (ky === "selections") {
angular.forEach(val, function(v, k) {
$http.get('/selections/' + v).then(function(response) {
var response = response.data;
$scope.selection = response[0];
$scope.selectionName = $scope.selection.name;
$scope.selections.push({name : $scope.selectionName});
value["selectionNames"] = $scope.selections;
})
})
}
})
value["selectionNames"] = $scope.selections;
console.log(value);
So I am iterating over a list of pots which contains a list of selections, using the GET/ to get a list of names based on the list of selections and finally pushing that into the pot's scope. I am resetting the selection after each pot.
What's causing the issue is that reponses all come at once, and they bypass the $scope.selections = []; code, so it just pushes into each pot the complete array from all three pots.
Any tips/advice please? Thank you.
So looks like I've fixed it... Can someone confirm that this is good practice please? I'm basically recreating $scope.selections each time I iterate based on the selectionNames value in the pot (value).
angular.forEach($scope.pots, function(value, key) {
$scope.selections = [];
angular.forEach(value, function(val, ky) {
if (ky === "selections") {
angular.forEach(val, function(v, k) {
$http.get('/selections/' + v).then(function(response) {
$scope.selections = [];
var response = response.data;
$scope.selection = response[0];
$scope.selectionName = $scope.selection.name;
var currentSelections = value.selectionNames;
angular.forEach(currentSelections, function(csV, csK) {
$scope.selections.push(csv);
})
$scope.selections.push({name : $scope.selectionName});
value["selectionNames"] = $scope.selections;
})
})
}
})
value["selectionNames"] = $scope.selections;
console.log(value);

Nodejs async data duplication

I'm having some problems with one async process on nodejs.
I'm getting some data from a remote JSON and adding it in my array, this JSON have some duplicated values, and I need check if it already exists on my array before add it to avoid data duplication.
My problem is when I start the loop between the JSON values, the loop call the next value before the latest one be process be finished, so, my array is filled with duplicated data instead of maintain only one item per type.
Look my current code:
BookRegistration.prototype.process_new_books_list = function(data, callback) {
var i = 0,
self = this;
_.each(data, function(book) {
i++;
console.log('\n\n ------------------------------------------------------------ \n\n');
console.log('BOOK: ' + book.volumeInfo.title);
self.process_author(book, function() { console.log('in author'); });
console.log('\n\n ------------------------------------------------------------');
if(i == data.length) callback();
})
}
BookRegistration.prototype.process_author = function(book, callback) {
if(book.volumeInfo.authors) {
var author = { name: book.volumeInfo.authors[0].toLowerCase() };
if(!this.in_array(this.authors, author)) {
this.authors.push(author);
callback();
}
}
}
BookRegistration.prototype.in_array = function(list, obj) {
for(i in list) { if(list[i] === obj) return true; }
return false;
}
The result is:
[{name: author1 }, {name: author2}, {name: author1}]
And I need:
[{name: author1 }, {name: author2}]
UPDATED:
The solution suggested by #Zub works fine with arrays, but not with sequelize and mysql database.
When I try to save my authors list on the database, the data is duplicated, because the system started to save another array element before finish to save the last one.
What is the correct pattern on this case?
My code using database is:
BookRegistration.prototype.process_author = function(book, callback) {
if(book.volumeInfo.authors) {
var author = { name: book.volumeInfo.authors[0].toLowerCase() };
var self = this;
models.Author.count({ where: { name: book.volumeInfo.authors[0].toLowerCase() }}).success(function(count) {
if(count < 1) {
models.Author.create(author).success(function(author) {
console.log('SALVANDO AUTHOR');
self.process_publisher({ book:book, author:author }, callback);
});
} else {
models.Author.find({where: { name: book.volumeInfo.authors[0].toLowerCase() }}).success(function(author) {
console.log('FIND AUTHOR');
self.process_publisher({ book:book, author:author }, callback);
});
}
});
// if(!this.in_array(this.authors, 'name', author)) {
// this.authors.push(author);
// console.log('AQUI NO AUTHOR');
// this.process_publisher(book, callback);
// }
}
}
How can I avoid data duplication in an async process?
This is because you are comparing different objects and result is always false.
Just for experiment type in the console:
var obj1 = {a:1};
var obj2 = {a:1};
obj1 == obj2; //false
When comparing objects (as well as arrays) it only results true when obj1 links to obj2:
var obj1 = {a:1};
var obj2 = obj1;
obj1 == obj2; //true
Since you create new author objects in each process_author call you always get false when comparing.
In your case the solution would be to compare name property for each book:
BookRegistration.prototype.in_array = function(list, obj) {
for(i in list) { if(list[i].name === obj.name) return true; }
return false;
}
EDIT (related to your comment question):
I would rewrite process_new_books_list method as follows:
BookRegistration.prototype.process_new_books_list = function(data, callback) {
var i = 0,
self = this;
(function nextBook() {
var book = data[i];
if (!book) {
callback();
return;
}
self.process_author(book, function() {
i++;
nextBook();
});
})();
}
In this case next process_author is being called not immediately (like with _.each), but after callback is executed, so you have consequence in your program.
Not sure is this works though.
Sorry for my English, I'm not a native English speaker

Resources