querySelector returns 'undefined' - javascript

<div id="~" class="dm-post-0 well clearfix post listview"
data-identifier="~" data-relative="https://~"
data-feed="~">
let convertEntries = () => {
"use strict";
let target = [...document.getElementsByClassName("listview")];
target.forEach((element) => {
result.push({
url: element.querySelector("#listview").dataset.relative,
});
});
return result;
};
How can I capture the contents of the data-relative attribute instead of returning undefined?

When you iterate over these elements in the HTML collection returned by getElementsByClassName you only need to get the dataset value from the current iterated element.
element.dataset.relative
Since you're doing an array-like collection => array conversion you may as well use map to build the array of objects to save declaring a separate result array.
And querySelectorAll is shorter to type.
function convertEntries() {
const list = [...document.querySelectorAll('.listview')];
return list.map(element => {
return { url: element.dataset.relative };
});
}
console.log(convertEntries());
<div id="~" class="dm-post-0 well clearfix post listview" data-identifier="~" data-relative="https://~" data-feed="~">
<div id="~" class="dm-post-0 well clearfix post listview" data-identifier="~" data-relative="https://~1" data-feed="~">

Related

How to return specific key from an Object

I have an Object which looks like this:
servers = {"ErrorCode":"0",
"NodeList":[{
"HostName":"d4",
"FQDN":"s3",
"Role":"GHI",
"productTypeId":"1",
"DNSResolved":"true"
},
{
"HostName":"a5",
"FQDN":"s2",
"Role":"ABC",
"productTypeId":"2",
"DNSResolved":"true"
},
{
"HostName":"a1",
"FQDN":"c1",
"Role":"DEF",
"productTypeId":"1",
"DNSResolved":"true"
}]
}
I want the NodeList key and out of which I want to extract the HostName. I have tried the following code to extract the NodeList and then to map over it. But the NodeList key is not even getting printed.
console.log('servers', Object.keys(servers).find(node => {
return servers[node] === 'NodeList';
}))
It returns undefined
servers["NodeList"].map(item=>item.HostName)

Can I use .includes() to determines whether an array includes a certain element based on an array of strings instead of a single string?

Right now if I use this snippet of code, I get all elements whose region property is "Demacia"
let filtered = this.cards.filter((card) => {
return card.region.includes("Demacia");
})
Now I want to be able to get all elements whose property region is either "Noxus" or "Demacia", however, this doesn't seem to work as it returns an empty array
let regions = ["Demacia", "Noxus"];
let filtered = this.cards.filter((card) => {
return card.region.includes(regions);
})
Can I even do that or do I need to look into other array functions?
Instead of trying to pass multiple options to includes, look inside regions to see if it contains the region of the current card
let regions = ["Demacia", "Noxus"];
let filtered = this.cards.filter((card) => {
return regions.includes(card.region);
})
Just adding my answer because Array.prototype.includes() is not supported in IE, so if you want to support old browser, you can do
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes#Browser_compatibility
let regions = ["Demacia", "Noxus"];
let filtered = this.cards.filter((card) => {
return regions.indexOf(card.region) > -1;
})

Javascript's method forEach() creates array with undefined keys

I am building a simple todo app, and I'm trying to get the assigned users for each task. But let's say that in my database, for some reason, the tasks id starts at 80, instead of starting at 1, and I have 5 tasks in total.
I wrote the following code to get the relationship between user and task, so I would expect that at the end it should return an array containing 5 keys, each key containing an array with the assigned users id to the specific task.
Problem is that I get an array with 85 keys in total, and the first 80 keys are undefined.
I've tried using .map() instead of .forEach() but I get the same result.
let assignedUsers = new Array();
this.taskLists.forEach(taskList => {
taskList.tasks.forEach(task => {
let taskId = task.id;
assignedUsers[taskId] = [];
task.users.forEach(user => {
if(taskId == user.pivot.task_id) {
assignedUsers[taskId].push(user.pivot.user_id);
}
});
});
});
return assignedUsers;
I assume the issue is at this line, but I don't understand why...
assignedUsers[taskId] = [];
I managed to filter and remove the empty keys from the array using the line below:
assignedUsers = assignedUsers.filter(e => e);
Still, I want to understand why this is happening and if there's any way I could avoid it from happening.
Looking forward to your comments!
If your taskId is not a Number or autoconvertable to a Number, you have to use a Object. assignedUsers = {};
This should work as you want it to. It also uses more of JS features for the sake of readability.
return this.taskLists.reduce((acc, taskList) => {
taskList.tasks.forEach(task => {
const taskId = task.id;
acc[taskId] = task.users.filter(user => taskId == user.pivot.task_id);
});
return acc;
}, []);
But you would probably want to use an object as the array would have "holes" between 0 and all unused indexes.
Your keys are task.id, so if there are undefined keys they must be from an undefined task id. Just skip if task id is falsey. If you expect the task id to possibly be 0, you can make a more specific check for typeof taskId === undefined
this.taskLists.forEach(taskList => {
taskList.tasks.forEach(task => {
let taskId = task.id;
// Skip this task if it doesn't have a defined id
if(!taskId) return;
assignedUsers[taskId] = [];
task.users.forEach(user => {
if(taskId == user.pivot.task_id) {
assignedUsers[taskId].push(user.pivot.user_id);
}
});
});
});

Loop through 2 Arrays and assign a value from one array into each matching objects of second array

I have 2 Arrays 1.Options and 2.sameAccountArray
options.map((opt, optInd) => {
sameAccountArray.map((acObj, acInd) => {
if (opt.optNumber === acObj.optNumber) {
console.log(opt.optNumber, acObj.optNumber, acObj.exist, acObj.exist, 'WTF', sameAccountArray);
opt.exist = acObj.exist;
} else {
console.log(opt, acObj, opt.optNumber, acObj.optNumber, 'kundi');
// opt.exist = false;
}
// else {
// if (optInd === acInd) {
// opt.exist = acObj.exist;
// } else {
// console.log('elseeee', optInd, acInd,opt.optNumber, acObj.optNumber, opt.exist, acObj.exist);
// }
// }
});
});
Data Structure of sameAccountArray:
{
'key': key,
'shares': this.no_of_shares[key],
'refValue': this.your_reference[key],
'exist': false,
'accountNumber': extractedAccountNumber, 'optNumber': parseInt(extractedOptionNumber)
}
Option have big fields inside, but we don't need to care about it. options and sameAccountArray have common filed named optNumber. I am trying loop through each array and assign a value named exist in each object of the options array if optNumber is same. sameAccountArray already has the correct exist value, I just need to assign that value to match objects of options array. Somehow it's not assigned correctly. Please note that options array and sameAccount Array is not the same length. sameAccountArray has dynamic objects while options have a fixed number of elements. Any idea what is going wrong here guys? Thanks in advance
Try this:
options.forEach(opt=>{
sameAccountArray.forEach(acObj=>{
if (opt.optNumber === acObj.optNumber) opt.exist = acObj.exist;
})
})
The map() method creates a new array with the results of calling a provided function on every element in the calling array.
You cannot modify your arrays with map() function, but only create a new array with the results you want.
let sameAccountObject={};
sameAccountArray.forEach((account)=>{
sameAccountObject[account.optNumber]=account;
});
let result=options.map((option)=>{
let account=sameAccountObject[option.optNumber];
if(account){
option.exist=account.exist;
}
return option;
});
console.log(result);

Javascript filter and match all elements in array

I have an array that looks like:
var testArr = ["40", "A1", "B9", "58"]
I want to loop over all div elements of a certain class and return only the elements where the data attribute matches ANY of the items in that array.
If I do something like this:
$("div.prodCodes").filter(function(e) {
var x1 = $(this);
var x2 = $(this).data("prodCode");
testArr.forEach(function(e) { if (e == x2) { console.log("MATCH"); } });
});
That console outputs the correct number of matches, but I cannot return those elements from the filter function.
What on earth am I missing here? I've tried creating a new array and pushing each item onto it and returning that, but it's always empty. I'm sure I'm missing something obvious here. I've also tried rewriting this using .grep() and getting nowhere. Help is appreciated.
You need to return a truthy value in filter() to have an item included.
Try :
$("div.prodCodes").filter(function(e) {
return testArr.indexOf($(this).attr('data-prodCode')) >-1;
}).doSomething();
Without a return all items will be excluded
I would use a Set for constant-time lookup.
Be aware that jQuery reads the attribute value "58" as a number when using the data method, so it won't match unless you make sure the data type is the same:
// Use a set
var testSet = new Set(["40", "A1", "B9", "58"]);
var texts = $("div.prodCodes").filter(function() {
var x = $(this).data("prodCode").toString(); // data type must match
// Return a boolean to indicate whether the div element should be kept
return testSet.has(x); // Set#has() is fast
}).map(function(){
// For demo only: get the text content of the matching div elements
return $(this).text();
}).get(); // convert that to a plain array
console.log(texts);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="prodCodes" data-prod-code="A1">Hello</div>
<div class="prodCodes" data-prod-code="XX">Not this one</div>
<div class="prodCodes" data-prod-code="58">There</div>

Categories