Why ngRepeat is not populated - javascript

I'm using ngRepeat in my angular application and for some reason the ngRepeat did not populate even though the collection that it is connected to is populated with the correct data.
What i'm doing is sending http get request to a node server to request the data,
go over the result from the server and populate a collection on the scope that is connected to that specific ngRepeat.
The ngRepeat part of the Html file:
<div id="cellRow" ng-repeat="obj in rowsCollection track by obj.index">
<div class="inputsContainer">
<input ng-model="obj.col1"></input>
<input ng-model="obj.col2"></input>
<input ng-model="obj.col3"></input>
</div>
</div>
The Ctrl code:
angular.module('App').controller('Ctrl', ['$scope','dataUtils', function($scope,dataUtils) {
$scope.dataObj = null;
$scope.rowsCollection = [];
dataUtils.getDataObj()
.then($scope.initializeObjects)
.catch($scope.showError);
$scope.initializeObjects = function(data) {
if( data && data.length > 0 ) {
for(var index = 0; index < 21; index++) {
$scope.dataObj = {};
$scope.dataObj.index = index + 1;
$scope.dataObj.col1 = data[0][index];
$scope.dataObj.col2 = data[1][index];
$scope.dataObj.col3 = data[2][index];
$scope.rowsCollection.push($scope.dataObj);
}
}
};
$scope.showError = function(errorMsg) {
console.log(errorMsg);
};
}]);
The dataUtils.getDataObj calls an http get request from the server.
When using the controller in this form i see that the initializeObjects function is called and the rowCollection collection is populated but the ngRepeat stays empty.
After i changed the Ctrl ro the following code:
angular.module('App').controller('Ctrl', ['$scope','dataUtils', function($scope,dataUtils) {
$scope.dataObj = null;
$scope.rowsCollection = [];
dataUtils.getDataObj()
.then(initializeObjects)
.catch(showError);
function initializeObjects(data) {
if( data && data.length > 0 ) {
for(var index = 0; index < 21; index++) {
$scope.dataObj = {};
$scope.dataObj.index = index + 1;
$scope.dataObj.col1 = data[0][index];
$scope.dataObj.col2 = data[1][index];
$scope.dataObj.col3 = data[2][index];
$scope.rowsCollection.push($scope.dataObj);
}
}
}
function showError(errorMsg) {
console.log(errorMsg);
}
}]);
The ngRepeat did populate, why didn't the ngRepeat populate in the first Ctrl configuration but did in the second ?

If you want to use the first way, since you're calling a function, it must have () at the end.
So to achieve what you want you should change this:
.then($scope.initializeObjects)
for:
.then($scope.initializeObjects())
Note: The second way is better, since you need to reuse this $scope function in another moment, otherwise, keep it as a normal function().

In ur first implementation, it should work when u put the $scope.initializeObjects =... before using it in the promise.
$scope.initializeObjects = function(data) {
if( data && data.length > 0 ) {
for(var index = 0; index < 21; index++) {
$scope.dataObj = {};
$scope.dataObj.index = index + 1;
$scope.dataObj.col1 = data[0][index];
$scope.dataObj.col2 = data[1][index];
$scope.dataObj.col3 = data[2][index];
$scope.rowsCollection.push($scope.dataObj);
}
}
};
$scope.showError = function(errorMsg) {
console.log(errorMsg);
};
dataUtils.getDataObj()
.then($scope.initializeObjects)
.catch($scope.showError);
However, if u declare your function as your second attempt, it will be defined before the code in this closure get executed.
You may check this question to understand the difference.

Related

how do I check if a value is in a JSON return or not?

I'm writing a test in postman where I want to check if a JSON return contains the Label called 'RegressieMapTest'. This is my script:
pm.test("Is the folder created correctly?", function(){
var jsonData = pm.response.json();
var objString = JSON.stringify(jsonData);
var obj = JSON.parse(objString);
for (var i = 0; i < obj.Corsa.Data.length; i++){
if (obj.Corsa.Data[i].Label == "RegressieMapTest"){
console.log(obj.Corsa.Data[i].Label);
pm.expect(obj.Corsa.Data.Label).to.eql("RegressieMapTest");
}
}
pm.expect.fail();
})
But it doesn't quite work, every time I run this script it seems like it automatically jumps to pm.expect.fail() which is weird because 'RegressieMapTest' is inside the JSON return. Postman returns the following message:
Is the folder created correctly? | AssertionError: expect.fail()
pm.respose.json() is equalent to JSON.parse you don't have to do it again
also you can use array.find method instead of looping through it
pm.test("Is the folder created correctly?", function () {
var jsonData = pm.response.json();
pm.expect(obj.Corsa.Data.find(elem => elem.Label === "RegressieMapTest")).to.be.not.undefined
}
if array has any element with label RegressieMapTest then it will return that data elese returns undefined, so we are validating that it will not return undefined. Meaning it has the value
Your pm.expect.fail(); always runs. You want it to run only when you don't find the field. So just add a flag in your check block.
pm.test("Is the folder created correctly?", function(){
var jsonData = pm.response.json();
var objString = JSON.stringify(jsonData);
var obj = JSON.parse(objString);
var isFound = false;
for (var i = 0; i < obj.Corsa.Data.length; i++){
if (obj.Corsa.Data[i].Label == "RegressieMapTest"){
console.log(obj.Corsa.Data[i].Label);
pm.expect(obj.Corsa.Data.Label).to.eql("RegressieMapTest");
isFound = true;
}
}
if (!isFound) {
pm.expect.fail();
}
})

Filling Data using Angular js filter method

I am new to Angular js,
I have the following code which binds data to the div,
app.filter("myfilter", function () {
return function (data, catName) {
if (angular.isArray(data) && angular.isString(catName)) {
var rs = [];
var key = {};
for (var i = 0; i < data.length; i++) {
var currdata = data[i][catName];
if (angular.isUndefined(key[currdata])) {
key[currdata] = true;
rs.push(currdata);
}
}
return rs;
}
else
return data;
}
})
But when i came across the code above i found a line "key[currdata] = true;"
what's this piece of code does?
when i comment this particular line data binding not happening?
Thanks in advance.
This line is just like a mark in order that in the next iteration the condition "angular.isUndefined..." is false and, in that way, it prevents push duplicated values into rs array.
it is simply checking that no duplicate key is pushed into rs

Angular Check All button

I have a handful of simple checkbox lists that I need to create for an application. I built a "Check All" button for my initial test and it worked beautifully. But, when I changed the code to fetch a subset of the list via a Node call, the list still appeared as expected, but the Check All functionality no longer did. In my initial test, the list was just an array of objects with "description" and "value" but after inserting Node into the middle, the objects also had a $$hashkey property. I'm not sure if this is the source of the problem, but if someone could take a look and tell me what's wrong, I'd appreciate it.
My HTML looks like this:
<div class="row">
<div class="col-md-3" id="semRushApiList_None">
<input type="checkbox" value="semRushCheckAll_None" name="semRushCheckAll_None" ng-click="toggleSemRushApiTypes_None()" /><strong>Check All</strong>
<div ng-repeat="apiCall in semRushApiTypes_None">
<input type="checkbox" name="selectedSemRushApiTypes_None[]" value="{{apiCall.apiName}}" ng-checked="selectedSemRushApiTypes_None.indexOf(apiCall) > -1" ng-click="toggleSemRushApiSelection_None(apiCall)" /> {{apiCall.description}}
</div>
</div>
</div>
My angular js looks like this:
$scope.semRushCheckAll_None = false;
$scope.semRushApiTypes_None = [];
fetchApiTypesByCategory("none").then(function(types){
$scope.semRushApiTypes_None = types;
});
$scope.selectedSemRushApiTypes_None = [];
$scope.toggleSemRushApiTypes_None = function() {
$scope.semRushCheckAll_None = !$scope.semRushCheckAll_None;
if ($scope.semRushCheckAll_None) {
$scope.selectedSemRushApiTypes_None = angular.copy($scope.semRushApiTypes_None);
} else {
$scope.selectedSemRushApiTypes_None = [];
}
};
$scope.toggleSemRushApiSelection_None = function(apiCall) {
var idx = $scope.selectedSemRushApiTypes_None.indexOf(apiCall);
if (idx > -1) {
$scope.selectedSemRushApiTypes_None.splice(idx, 1);
} else {
$scope.selectedSemRushApiTypes_None.push(apiCall);
console.log(JSON.stringify($scope.selectedSemRushApiTypes_None));
}
};
function fetchApiTypesByCategory(category) {
var deferred = $q.defer();
$http.get(rootApiUrl + "/fetchSemRushApiTypesByCategory?category=" + category).then(function(response) {
deferred.resolve(response.data);
}, function(response){
deferred.reject("Error: " + response.data);
});
return deferred.promise;
}
The node call looks like this:
server.route({
method:"GET",
path:"/fetchSemRushApiTypesByCategory",
handler:function(request,reply){
var q = Qs.parse(request.query);
return reply(factory.createApiTypeList(q["category"])).code(200);
}
});
and the factory looks like this:
exports.createApiTypeList = function(category) {
var result = [];
for (var i = 0; i < semRushApiJson.length; i++) {
if (semRushApiJson[i].category === category) {
var description = semRushApiJson[i].description;
var apiName = "";
for (var p = 0; p < semRushApiJson[i].params.length; p++) {
if (semRushApiJson[i].params[p].key == "type") {
apiName = semRushApiJson[i].params[p].value;
break;
}
}
result.push({
"description": description,
"apiName": apiName
});
}
}
return result;
};
Some simple console.log statements have proven that things are being populated as expected, with the exception of the $$hashkey property on the objects coming out of the Node call.
When I check the checkboxes individually, the selected array is populated with a value that doesn't have the $$hashkey and when I check the check all, the selected list gets all of the appropriate values including the $$hashkey, but the checkboxes do not get updated on the UI like they did before I moved the populating of the list to a Node call.
Can anyone tell me what I'm doing wrong here?
V

Element Array Access within a Deferred Object

How would I access the values of 'timestamp' and 'usage' in the following example,
function executeReadingsQuery(query, postQueryProcessing) {
var d = new $.Deferred();
var processing = function(tx, results) {
var result = [];
var len = results.rows.length;
for ( var i = 0; i < len; i++) {
result.push({
"timestamp" : moment(results.rows.item(i).timeStamp),
"usage" : results.rows.item(i).usage
});
}
if (postQueryProcessing) {
result = postQueryProcessing(result);
}
d.resolve(result);
};
executeQuery(query, processing);
return d;
}
A function that builds a query string will subsequently call the above function,
function getReadingsInternal(noOfReadings, postQueryProcessing) {
var query = "SELECT * from usage ORDER BY timestamp DESC limit " + noOfReadings.toString();
return executeReadingsQuery(query, postQueryProcessing);
}
And then there is another function that exposes the entire functionality globally,
getReadings : function(noOfReadings) {
return getReadingsInternal(noOfReadings);
}
The original function (the first one listed) is within a Variable called WNDatabase
So I can access the function with a call that looks like this
WNDatabase.getReadings(30)
But I would like to be able to also globally access the values of timestamp and usage which populate the result[] array of the deferred object.
It seems that it is not possible to do something like this
$.when(WNDatabase.getReadings(30)).done(function() {
for(var i=0; i<7; i++){
console.log(this[i].usage);
}
});
So what would one do in this event?

AngularJS - Collecting multiple get requests into json array and then passing to directive

I am new to angular and been struggling how to solve my problem.
I need to access API multiple times for users data, store everything as JSON array and when all the data is collected(all results as one array) it needs to be passed to directive which will use it to draw visualization(eg. d3.js-pie chart).
$scope.allData = [];
$http.get("****link here****/students")
.success(function (data) {
students = data;
for (i = 0; i < students.length; i = i + 1) {
$http.get("**** link here ****/quest/" + students[i].id)
.success(function (data) {
quest = data;
$scope.allData.push({
id: quest.id,
value: quest.length
});
}
}
and then pass it to directive as
<bar-chart data='allData'></bar-chart>
even if I set watch in directive and have scope as '=' the directive gets empty array.
In my other code when I just do one http get call for json array I can pass it to directive easily and it works fine.
EDIT1:
OK so I use premises now, but still allData array is 0.
Even with simple example like this:
$scope.allData = [];
var promieses = [];
for (i = 0; i < 10; i = i + 1) {
promieses.push($http.get("***link***/student/" + students[i].id));
}
$q.all(promieses).then(function (data) {
for (i = 0; i < data.length; i = i + 1) {
$scope.allData.push("test");
}
});
in html {{ allData ]] // 0
This is a great place to unleash the power of $q. You can wait for all the promises to resolve and then process them using $q.all method. It simply Combines multiple promises into a single promise that is resolved when all of the input promises are resolved.
See this example:
students = data;
var promises = [];
for (i = 0; i < students.length; i = i + 1) {
promises.push($http.get("**** link here ****/quest/" + students[i].id));
}
$q.all(promises).then(function(response) {
for (var i = 0; i < response.length; i++) {
$scope.allData.push({
id: response[i].data.id,
value: response[i].data.length
});
}
})
See it in action here: http://plnkr.co/edit/TF2pAnIkWquX1Y4aHExG?p=preview

Categories

Resources