equating last value in loop problem in innerHtml - javascript

forecasts is array who has a 10 elements when ı try to print its work perfectly when ı use innerHtml its giving the last value of items and everything is look same
const getOtherDays = (data) => {
data.forecasts.forEach((forecast)=>{
for(var i = 0; i < day.length; i++) {
items = forecast.day;
console.log(items)
day[i].innerHTML = `${items}`
}
})
}

You shouldn't use a nested loop. If each element of data.forecasts is for a different day, use the index in that array to assign to the corresponding DOM element.
const getOtherDays = (data) => {
data.forecasts.forEach((forecast, i) => {
items = forecast.day;
console.log(items)
day[i].innerHTML = `${items}`
})
}

You are looping over the elements and setting it to the forecast of the day on every one. You want to select the specific element. The forEach index has the index. Hopefully that index matches the day in your elements. Basic idea:
const getOtherDays = (data) => {
data.forecasts.forEach((forecast, index)=>{
items = forecast.day;
day[index].innerHTML = `${items}`;
})
}

Related

Push all objects after a selected object into an array

I have a web page that returns a list of objects like:
date.pdf
names.csv
address.pdf
age.csv
cost.csv
budget.csv
data.pdf
race.pdf
contractors.csv
When a user checks budget.csv, I want every object with the .csv extension from that point to be pushed into csv_files[]. If they select names.csv, then every .csv including and after names is pushed into the array.
So the only data that gets pushed into the array is from the selected object downwards. How can I implement this?
Current code
const csv_files = []
$scope.listAllobjects = (err, data) => {
$.each(data.Contents, (index, value) => {
if (value.Key.endsWith("csv")) {
csv_files = [];
}
// Handle click on selection checkbox
$("#filesobjects-table tbody").on("click", 'input[type="checkbox"]', (e1) => {
const checkbox = e1.currentTarget;
const $row = $(checkbox).closest("tr");
const data = $tb.DataTable().row($row).data();
let index = -1;
// Prevent click event from propagating to parent
e1.stopPropagation();
// Find matching key in currently checked rows
index = $scope.view.keys_selected.findIndex((e2) => e2.Key === data.Key);
if (checkbox.checked && data.Key.endsWith("csv")) {
console.log(selected csv)
}
});
}
There's a few ways, I suppose, to approach this problem, but the most intuitive to me is this:
const csvList = ["date.pdf","names.csv","address.pdf","age.csv","cost.csv","budget.csv","data.pdf","race.pdf","contractors.csv"];
const selectedCsv = 'budget.csv';
function getCsvsAfter(csvList, selectedCsv) {
const filteredCsvs = [];
let found = false;
for (let csv of csvList) {
if (csv === selectedCsv) found = true;
if (found) filteredCsvs.push(csv);
}
return filteredCsvs;
}
console.log(getCsvsAfter(csvList, selectedCsv));
Iterate over every csv, and when you've hit the one you're trying to match, set a variable called found to true. Once it's true, you can add every following csv onto the list.
const list = ['date.pdf','names.csv','address.pdf','age.csv','cost.csv','budget.csv','data.pdf','race.pdf','contractors.csv'];
const selected = 'budget.csv'
const csv_files = list.slice(list.indexOf(selected))
console.log(csv_files)
Here you go with a pure JavaScript solution (Descriptive comments has been added in the below code snippet).
var contentData = ["date.pdf", "names.csv", "address.pdf", "age.csv", "cost.csv", "budget.csv", "data.pdf", "race.pdf", "contractors.csv"];
var myDiv = document.getElementById("cboxes");
for (var i = 0; i < contentData.length; i++) {
var checkBox = document.createElement("input");
var label = document.createElement("label");
checkBox.type = "checkbox";
checkBox.value = contentData[i];
myDiv.appendChild(checkBox);
myDiv.appendChild(label);
label.appendChild(document.createTextNode(contentData[i]));
}
// Event to handle the checkbox click
document.getElementById('getResult').addEventListener('click', () => {
document.getElementById('showResult').innerHTML = getCheckedValues();
});
function getCheckedValues() {
// filtered out the checked items.
const element = Array.from(document.querySelectorAll('input[type="checkbox"]'))
.filter((checkbox) => checkbox.checked).map((checkbox) => checkbox.value);
// element[0] will always return the first checked element and then we are getting index of that.
const checkedElemIndex = contentData.indexOf(element[0]);
// Slice the content data to get the elements from the checked element index.
return contentData.slice(checkedElemIndex, contentData.length)
}
<div id="cboxes"></div>
<button id="getResult">Get Result</button>
<pre id="showResult"></pre>

Push elements that don't have a specific class into an array

I tried to make a function looking for elements that don't have class "check", in this case I got it. Then I wanted to push them into an array so I got length, but what I got wasn't what I expected, do you have any solution for this case?
PLESAE READ MY COMMENTS IN THE CODES
What i wanted is to get the length of list that does not have class "check"
const countUnactiveList =()=> {
let list = [...todoList.children];
let listArr = [];
list.filter(child => {
if(!child.classList.contains('check')) {
console.log(child); //it works, i got the lists that does not have class "check"
listArr.push(child);
console.log(listArr.length); //the output are 1 2 3 creeping down. But it should be 3
}
});
}
Array.prototype.filter returns a new array and you're logging the length in each iteration.
here's the fixed code:
const countUnactiveList = () => {
const list = [...todoList.children];
const listArr = list.filter(child => {
return !child.classList.contains('check');
});
console.log(listArr, listArr.length);
return listArr.length;
}
based on the function name, I think you're just interested in the count. You can return the length of the filtered array.
An alternate approach using reduce:
const countUnactiveList = () => {
const list = [...todoList.children];
return list.reduce((count, child) => {
if(!child.classList.contains('check')) {
count += 1;
}
return count;
}, 0)
};

How do I prevent two identical elements to be printed in a table?

I'm writing a javascript code, where the user should be able to search through dimension elements, which is displayed within a "pop-up" window with a table.
The code that displays the elements in the array looks like this:
$element.find("#myInput").on("qv-activate", function (){
let elemList = [];
self.backendApi.getData(requestList).then(function (dataPages) {
let elem = dataPages[0].qMatrix;
for(let i = 0; i < elem.length; i++){
elemList.push(elem[i][0].qText);
}
$(document).ready(function () {
$("#myInput").on("keyup", function () {
var value = $(this).val().toLowerCase();
for (var i=0; i<elemList.length; i++) {
if (elemList[i].toLowerCase().indexOf(value) >= 0){
$element.find('#searchTable').prepend('<tr><td id="searchElem">' + elemList[i] + '</td></tr>');
}
}
});
});
})
})
The only problem is, when I use the searchbar, it presents the element multiple times. Is there a way I can make sure, that the .prepend() only prepends if it is not the same value as before?
Some kind of; if element value is identical with the before prepended value, then don't prepend?
Hope it makes sense, and you have a solution to my problem.
Thanks!
Instead of calling prepend in the second for loop, make a new array and append elemList[i] to that.
Then use a solution from "Get all unique values in an array (remove duplicates)" to remove the duplicates from the array. For example, if values is your new array:
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
values = values.filter(onlyUnique);
Finally, loop through your new array and call prepend on each.

appendChild() fails when trying to append a value stored in an array

The following code deletes all children of a certain element, besides these listed inside the saved variable.
let rightCol = document.querySelector("#rightCol");
let saved = rightCol.querySelectorAll('._4-u2._3-96._4-u8');
let savedArr = [];
saved.forEach(()=>{
savedArr.push(saved);
});
rightCol.innerHTML = ''; // Delete all children before retrieving "saved" ones.
for (var i = 0; i < savedArr.length; i++) {
rightCol.appendChild(savedArr[i]);
};
The code fails with this error:
TypeError: Argument 1 of Node.appendChild does not implement interface Node.
Why the code fails?
The code you presented have 2 errors:
querySelectorAll should be executed on document.
you are pushing entire array in for each loop.
here is the working copy
let rightCol = document.querySelector("#rightCol");
let saved = document.querySelectorAll('._4-u2._3-96._4-u8');
let savedArr = [];
saved.forEach((s)=> {
savedArr.push(s);
});
rightCol.innerHTML = ''; // Delete all children before retrieving "saved" ones.
for (var i = 0; i < savedArr.length; i++) {
rightCol.appendChild(savedArr[i]);
};
You are pushing your collection array for each element in your selection return instead of the elements
Where your code state .each(()=> on the next line, the argument to push should be this
On each iteration of forEach you are adding the entire saved array to savedArr. You should instead add each item using the parameter passed into the forEach callback.
e.g.
saved.forEach((s)=> {
savedArr.push(s);
});
Not sure why you're copying the array over to another array here though..

Return Object in Array if Property Match

Here is the scenario:
There is a parameter titledlistOfSelectedProductIdsthat contains
all of the selected ids.
There is another list titled listOfAllPossibleProducts, which
contains a list of objects. That object contains a ProductId,
ProductName, and ProductCode. It looks something like this:
The task at hand:
I need to loop through my listOfSelectedProductIds. If the ProductId matches a ProductId from listOfAllPossibleProducts, then I need to return that object.
Here is what I am doing:
function SelectedProducts(listOfSelectedProductIds){
for (var index = 0; index < listOfSelectedProductIds.length; index++) {
var currentItem = listOfSelectedProductIds[index];
var desiredProduct = _.contains(listOfAllPossibleProducts, currentItem);
if (desiredProduct === true) {
return listOfAllPossibleProducts[index];
}
}
}
What's currently happening:
My loop is getting the selected id as expected i.e. currentItem, but _.contains(...)
always returns false.
Question:
What is the best way to find the objects in
listOfAllPossibleProducts that have ProductIds that match my
ProductIds in the listOfSelectedProductIds
How about using _.filter:
var result = _.filter(listOfAllPossibleProducts, function (el) {
return _.contains(listOfSelectedProductIds, el.id);
});
Or the non-underscore method:
var result = listOfAllPossibleProducts.filter(function (el) {
return listOfSelectedProductIds.indexOf(el.id) > -1;
});
DEMO
create another structure productsByProductId once!
var productsByProductId = {};
listOfAllPossibleProducts.forEach(p => {
productsByProductId[p.ProductId()] = p
});
and maybe a helper function
function getProductById(id){
return productsByProductId[id];
}
and use this to map the ids to the nodes
var selectedProducts = listOfSelectedProductIds.map(getProductById)

Categories