This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
I have angular ui grid that I am trying to get values from its cells. Here is my list in table
id name
1 AUSTRIA
2 BELGIUM
3 BULGARIA
4 CROATIA
5 CZECH REPUBLIC
This is code I run:
element(by.id('grid1')).all(by.repeater('(rowRenderIndex, row) in rowContainer.renderedRows track by $index')).then(function (items) {
for (var i = 0; i < items.length; i++) {
var country = <any>{}; //typescript code
self.gridTestUtils.dataCell('grid1', i, 0).getText().then(
function (valueId) {
country.id = valueId
});
self.gridTestUtils.dataCell('grid1', i, 1).getText().then(
function (valueName) {
country.name = valueName;
self.countryList.push(country)
console.log(self.countryList)
});
}
});
And this is result
[ { id: 1, name: 'AUSTRIA' }]
[ { id: 1, name: 'BELGIUM' },
{ id: 1, name: 'BELGIUM' }]
[ { id: 1, name: 'BULGARIA' },
{ id: 1, name: 'BULGARIA' },
{ id: 1, name: 'BULGARIA' } ]
[ { id: 1, name: 'CROATIA' },
{ id: 1, name: 'CROATIA' },
{ id: 1, name: 'CROATIA' },
{ id: 1, name: 'CROATIA' } ]
[ { id: 1, name: 'CZECH REPUBLIC' },
{ id: 1, name: 'CZECH REPUBLIC' },
{ id: 1, name: 'CZECH REPUBLIC' },
{ id: 1, name: 'CZECH REPUBLIC' },
{ id: 1, name: 'CZECH REPUBLIC' } ]
I expect result would look like:
[ { id: 1, name: 'AUSTRIA' }]
[ { id: 1, name: 'AUSTRIA' },
{ id: 1, name: 'BELGIUM' }]
[ { id: 1, name: 'AUSTRIA' },
{ id: 1, name: 'BELGIUM' },
{ id: 1, name: 'BULGARIA' } ]
[ { id: 1, name: 'AUSTRIA' },
{ id: 1, name: 'BELGIUM' },
{ id: 1, name: 'BULGARIA' },
{ id: 1, name: 'CROATIA' } ]
[ { id: 1, name: 'AUSTRIA' },
{ id: 1, name: 'BELGIUM' },
{ id: 1, name: 'BULGARIA' },
{ id: 1, name: 'CROATIA' },
{ id: 1, name: 'CZECH REPUBLIC' } ]
What is wrong with my code? What should I do that I have expected array
The problem is that i in your loop changes as the loops goes through, and in your async calls you are using i and getting a promise, but it's only a reference, so at the time the promises get resolved, the will have the reference to the variable with the last value of the loop. A workaround is to create an IIFE:
element(by.id('grid1')).all(by.repeater('(rowRenderIndex, row) in rowContainer.renderedRows track by $index')).then(function (items) {
for (var i = 0; i < items.length; i++) {
var country = <any>{}; //typescript code
(function (i, country) {
self.gridTestUtils.dataCell('grid1', i, 0).getText().then(function (valueId) {
country.id = valueId;
});
self.gridTestUtils.dataCell('grid1', i, 1).getText().then(function (valueName) {
country.name = valueName;
self.countryList.push(country)
console.log(self.countryList)
});
})(i, country);
}
});
Related
I have an array called data. How do i extract sub_data? Just need the sub_data part for each object.
const data = [
{
id: 1,
title: 'Logo'
sub_data: [
{
id: 2,
title: 'Company Logo'
},
{
id: 3,
title: 'Website Logo'
},
]
},
{
id: 2,
title: 'Brands'
sub_data: [
{
id: 25,
title: 'Company Brands'
},
{
id: 3,
title: 'Website Brands'
},
]
}
]
Example output will get two outputs because there is 2 objects:
const subData = [
{
id: 2,
title: 'Company Logo'
},
{
id: 3,
title: 'Website Logo'
},
]
const subData = [
{
id: 25,
title: 'Company Brands'
},
{
id: 3,
title: 'Website Brands'
},
]
Not very sure how to use the map function just to get sub_data in the correct structure
You can use flatMap to get sub_data in one array
const data = [
{
id: 1,
title: 'Logo',
sub_data: [
{
id: 2,
title: 'Company Logo'
},
{
id: 3,
title: 'Website Logo'
},
]
},
{
id: 2,
title: 'Brands',
sub_data: [
{
id: 25,
title: 'Company Brands'
},
{
id: 3,
title: 'Website Brands'
},
]
}
]
const result = data.flatMap(item => item.sub_data)
console.log(result)
If you want an array with the sub_data objects you can just map the original array:
const data = [
{
id: 1,
title: 'Logo',
'sub_data'
: [
{
id: 2,
title: 'Company Logo'
},
{
id: 3,
title: 'Website Logo'
},
]
},
{
id: 2,
title: 'Brands',
sub_data: [
{
id: 25,
title: 'Company Brands'
},
{
id: 3,
title: 'Website Brands'
},
]
}
]
const mappedData = data.flatMap(obj => obj.sub_data)
console.log(mappedData)
Another solution would be to use the .forEach function of javascript.
const subData = [];
data.forEach(item => subData.push(...item.sub_data))
var arr = [
{ id: 1, name: 'Ahmed Malick', school: 'TEWGS' },
{ id: 2, name: 'Tehmeed Anwar', school: 'DGS' },
{ id: 3, name: 'Azhar Yameen', school: 'DGS' }
]
I want this output:
The student name is his id is and he studies in
Can you please show me what kind of output you expect. Then i will try to solve it.
I'm not sure if this is what you want
var arr = [
{ id: 1, name: "Ahmed Malick", school: "TEWGS" },
{ id: 2, name: "Tehmeed Anwar", school: "DGS" },
{ id: 3, name: "Azhar Yameen", school: "DGS" },
];
arr.map((student) => {
return `Name: ${student.name}, id: ${student.id}, he studies in: ${student.school}`;
}).forEach((output) => {
console.log(output);
});
If you want it in the DOM do this
let html = arr.map((student) => {
return `<p><strong>Name</strong>: ${student.name}, <strong>id</strong>: ${student.id},<strong> he studies in</strong> ${student.school}</p>`;
}).join("")
document.createElement("div").innerHTML = html
Try thatGood luck
I have a object array in which each object contain an id and a name and a separate array contains a set of ids. I want to filter first array based on the second array.
const data= [
{
id: 1,
name: 'name1'
},
{
id: 2,
name: 'name2'
},
{
id: 3,
name: 'name3'
},
{
id: 4,
name: 'name4'
}
];
const array = [1,3,4];
const expectedResult= [
{
id: 1,
name: 'name1'
},
{
id: 3,
name: 'name3'
},
{
id: 4,
name: 'name4'
}
];
Use .filter and .includes
const data= [
{
id: 1,
name: 'name1'
},
{
id: 2,
name: 'name2'
},
{
id: 3,
name: 'name3'
},
{
id: 4,
name: 'name4'
}
];
const array = [1, 3, 4]
const result = data.filter((item) => {
//gives us items that passes a condition
return array.includes(item.id)
})
console.log(result)
i have multiple data for one id , i want filter my data like this
$scope.mpArray =[
{ Id: 1, Name: Madhu, Address: Upal },
{ Id: 1, Name: Chandu, Address: Upal },
{ Id: 2, Name: Srinu, Address: Kphb },
{ Id: 2, Name: Vijay, Address: kphb },
{ Id: 3, Name: Ajay, Address: Banglore },
{ Id: 3, Name: Narsi, Address: Banglore },
{ Id: 3, Name: Peter, Address: Banglore },
];
i want to filter my array like this
var FilterArray = [
{ Id: 1,Madhu, Chandu},
{ Id: 2, Srinu, Vijay},
{ Id: 3, Ajay, Narsi, Peter},
];
At first you need to change your FilterArray to
[
{
"Id": 1,
"Name": [
"Madhu",
"Chandu"
]
},
{
"Id": 2,
"Name": [
"Srinu",
"Vijay"
]
},
{
"Id": 3,
"Name": [
"Ajay",
"Narsi",
"Peter"
]
}
]
Notice that name is an array. The FilterArray of your question
var FilterArray = [
{ Id: 1,Madhu, Chandu},
{ Id: 2, Srinu, Vijay},
{ Id: 3, Ajay, Narsi, Peter},
];
Do not contain a valid JSON object inside the array so you need to change the structure to the one where add a new key Name in the JSON object of FilterArray as like the first structure above. Then the below code works great.
$(document).ready(function(){
var myArray =[
{ Id: 1, Name: "Madhu", Address: "Upal" },
{ Id: 1, Name: "Chandu", Address: "Upal" },
{ Id: 2, Name: "Srinu", Address: "Kphb" },
{ Id: 2, Name: "Vijay", Address: "kphb" },
{ Id: 3, Name: "Ajay", Address: "Banglore" },
{ Id: 3, Name: "Narsi", Address: "Banglore" },
{ Id: 3, Name: "Peter", Address: "Banglore" },
];
var FilterArray = [];
var matched;
for(var i=0;i<myArray.length; i++){
matched = false;
var myArrayId = myArray[i].Id;
for(var j=0; j<FilterArray.length; j++){
var FilterArrayId = FilterArray[j].Id;
if(myArrayId === FilterArrayId){
matched = true;
FilterArray[j].Name.push(myArray[i].Name);
// no need to loop further
break;
}
}
if(!matched){
var obj = {
'Id' : myArrayId,
'Name' : [myArray[i].Name],
}
FilterArray.push(obj);
}
}
console.log(FilterArray);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
try this
var mpArray =[
{ Id: 1, Name: 'Madhu', Address: 'Upal' },
{ Id: 1, Name: 'Chandu', Address: 'Upal' },
{ Id: 2, Name: 'Srinu', Address: 'Kphb' },
{ Id: 2, Name: 'Vijay', Address: 'kphb' },
{ Id: 3, Name: 'Ajay', Address: 'Banglore' },
{ Id: 3, Name: 'Narsi', Address: 'Banglore' },
{ Id: 3, Name: 'Peter', Address: 'Banglore' },
];
var filterObject = {};
mpArray.forEach(function (item) {
if (!filterObject[item.Id]) {
filterObject[item.Id] = [];
}
filterObject[item.Id].push(item.Name);
});
console.log(filterObject);
$scope.mpArray =[
{ Id: 1, Name: 'Madhu', Address: 'Upal' },
{ Id: 1, Name: 'Chandu', Address: 'Upal' },
{ Id: 2, Name: 'Srinu', Address: 'Kphb' },
{ Id: 2, Name: 'Vijay', Address: 'kphb' },
{ Id: 3, Name: 'Ajay', Address: 'Banglore' },
{ Id: 3, Name: 'Narsi', Address: 'Banglore' },
{ Id: 3, Name: 'Peter', Address: 'Banglore' },
];
var FilterArray = [];
var FilteredArrayIds=[];
$scope.mpArray.forEach(
function(detailObj) {
if(FilteredArrayIds.indexOf(detailObj.Id)==-1)
return FilteredArrayIds.push(detailObj.Id);
});
for(var i=0; i<FilteredArrayIds.length;i++)
{
var result = $scope.mpArray.filter(function( obj ) {
return obj.Id == FilteredArrayIds[i];
});
var rsltNames = result.map(function(obj){
return obj.Name;
})
var filteredObj ={
id:FilteredArrayIds[i]+',' +rsltNames.join()
}
FilterArray.push(filteredObj);
}
console.log(filteredObj)
I have a group of arrays on my Angular2 app that I use to build a grouped list with *ngFor in my view:
[
{
category: 1,
items: [{ id: 1, name: "helloworld1" }, { id: 2, name: "helloworld2" }]
},
{
category: 2,
items: [{ id: 3, name: "helloworld3" }, { id: 4 }]
},
{
category: 3,
items:[{ id: 5 }, { id: 6 }]
}
]
I also have a boolean that when it's true should filter only the items that have the name property. If a group does not have any item that matches this condition it should not pass. So the result would be the following if the boolean is true:
[
{
category: 1,
items: [{ id: 1, name: "helloworld1" }, { id: 2, name: "helloworld2" }]
},
{
category: 2,
items: [{ id: 3, name: "helloworld3" }]
}
]
How can I implement a pipe to achieve this kind of result?
http://plnkr.co/edit/je2RioK9pfKxiZg7ljVg?p=preview
#Pipe({name: 'filterName'})
export class FilterNamePipe implements PipeTransform {
transform(items: any[], checkName: boolean): number {
if(items === null) return [];
let ret = [];
items.forEach(function (item) {
let ret1 = item.items.filter(function (e) {
return !checkName || (checkName && (e.name !== undefined));
});
if(ret1.length > 0) {
item.items = ret1;
ret.push(item);
}
});
return ret;
}
}