Customer List Challenge (TestDome) - javascript

I'm trying to solve this challenge from TestDome and i need some help. I dont really understand how i must toggle the email and how to append the item to DOM...
!!Please without Vanilla JS only!!
Implement the showCustomers function so that it renders customers as list items. The first argument to the function, customers, is an array of objects with the name and email properties. The second argument to the function, targetList, is an unordered HTML list to which each customer should be added as a separate list item.
The name and email properties should be added as two paragraphs inside the list item. At first, the email paragraph element should not be present in the DOM. The email paragraph element should be added to the DOM after the name is clicked, and it should be removed from the DOM when the name is clicked again.
For example, the following code:
document.body.innerHTML = `
<div>
<ul id="customers">
</ul>
</div>
`;
let customers = [{name: "John", email: "john#example.com"},
{name: "Mary", email: "mary#example.com"}];
showCustomers(customers, document.getElementById("customers"));
let customerParagraph = document.querySelectorAll("li > p")[0];
if(customerParagraph) {
customerParagraph.click();
}
console.log(document.body.innerHTML);
Should render:
<div>
<ul id="customers">
<li>
<p>John</p>
<p>john#example.com</p>
</li>
<li>
<p>Mary</p>
</li>
</ul>
</div>
THIS IS MY CODE
function showCustomers(customers, targetList) {
customers.forEach(item =>{
let res = `<li>
<p> ${item.name}</p>;
<p> ${item.email}</p>;
</li>;
targetList.innerHTML = targetList.appendChild(res);
})
}
https://www.testdome.com/questions/javascript/customer-list/49798?visibility=3&skillId=2

Replace the line
targetList.innerHTML = targetList.appendChild(res);
with
targetList.innerHTML += res;.
You basically have two ways for adding elements:
increasing innerHTML contents with raw strings
appending children to DOM element
In your case res is a string so you can't use targetList.appendChild

Since you asked :
'The email paragraph element should be added to the DOM after the name is clicked, and it should be removed from the DOM when the name is clicked again'.
create list el,create p el, create event listener on p el, append email to a child element
Replace your code to
customers.forEach((item) => {
const li = document.createElement("li");
const name = document.createElement("p");
name.textContent = item.name;
name.style.cursor = "pointer";
name.addEventListener("click", (event) => {
const parent = event.target.parentElement;
if (parent.children.length == 1) {
const email = document.createElement("p");
email.textContent = item.email;
parent.appendChild(email);
} else {
parent.lastChild.remove();
}
});
li.appendChild(name);
targetList.appendChild(li);
});

function showCustomers(customers, targetList) {
customers.forEach((customer, index) => {
const node = document.createElement('li');
let nameEl = document.createElement('p');
let emailEl = document.createElement('p');
nameEl.innerText = customer.name;
emailEl.innerText = customer.email;
node.appendChild(nameEl);
nameEl.addEventListener('click', function() {
node.contains(emailEl) ? node.removeChild(emailEl) :
node.appendChild(emailEl);
});
targetList.appendChild(node)
});
}

Related

Can't save DOM element .value property to a variable

I'm trying to create a simple Javascript program that adds/removes items to an array, then displays the array by DOM manipulation.
I've created a reference called 'input', that is supposed to be the value of the HTML text input field. It's supposed to look like this:
let input = document.getElementById("text").value;
When I try to identify that variable in the console, it recognizes it as undefined. But, if I reference the variable like this:
let input = document.getElementById("text");
and call, input.value, it shows the appropriate value. For ex: "Lorem ipsum". What am I doing wrong?
I've provided a codepen link to see the output.
HTML
<div>
<form>
<input type ="text" id="text">
<button onClick="updateList(input.value)" type ="button">Add</button>
<button onClick = "reset()" type="button">Clear</button>
</form>
</div>
<div id='para'>
<!--list goes here-->
</div>
Javascript
//input.value will be used
let input = document.getElementById("text");
let groceryList = ["Grapes", "Juice", "Apples"];
//Div where output will be placed
let para = document.getElementById('para');
//Creation of ul
let unorderedList = document.createElement('ul');
para.appendChild(unorderedList);
//Creates list on DOM
const createList = groceryList.forEach((grocery) =>
{
//Creation of list item
let li = document.createElement('li');
li.innerText = grocery; // For instance, just to give us something to see
li.className = "grocery-item";
unorderedList.appendChild(li);
});
//Resets para
const reset = () => {
para.removeChild();
}
//Adds item
const updateList = (item) => {
reset();
groceryList.push(item);
return createList;
}
If you use let input = document.getElementById("text").value; you assign the initial value of your input field which is undefined at start to your variable.
This value will never change.
If you use let input = document.getElementById("text"); you set a reference to the input field to your variable and you can then retrieve the current value of this element by using input.value
I hope that my answer will be understandable because my English is really poor.

Check if element contains child with data id

const addToList = function ({ name, id }) {
let html1 = `
<li class="list-item" data-id="${id}" id="${id}">
${name}
<span>&nbsp</span>
<button class="btn-remove">remove</button>
</li>
`;
pokemonList.insertAdjacentHTML('beforeend', html1);
};
const displayListItem = function () {
favourite.forEach((listItem) => {
addToList(listItem);
});
};
let favourite = getStorageItem('pokemon');
pokemonContainer.addEventListener('click', function (e) {
if (e.target.classList.contains('btn-favourites')) {
favourite = getStorageItem('pokemon');
let eTargetID = parseInt(e.target.dataset.id);
let found = favourite.some((el) => el.id === eTargetID);
console.log(found);
console.log(eTargetID);
if (!found) {
favourite.push(pokemonArray[e.target.dataset.id - 1]);
setStorageItem('pokemon', favourite);
// behöver lösa duplcates i favorit listan
displayListItem(favourite);
}
}
});
How do I check if a child element with a dataset id exists? I want to prevent duplicate from appearing in my favourite list when I get them from local storage when I click on a button, if a li tag already exists with a specific dataset id.
Right now when I click let's say bulbasaur, I get bulbasaur in my list. If i then click ivysaur, I get bulbasaur, bulbasaur, ivysaur.
Thanks!
You can use querySelector, that dynamically accepts an id to search, for example:
document.querySelector(`[data-id="${datasetId}"]`)
Returns the element if exists, if not returns null.

pass information from a click event that is inside a Foreach to a variable

I want to get the value of "indx" generated by the for each to store it in a variable and use it globally in another operation. aid
<>
let table = ``;
await viewData.forEach((category, indx) => {
table += `
<div >
<li key="${indx}" onclick="(console.log(${indx}))" class="list-group-item" >
${category.name}
</li></div>
`
});
evento.innerHTML = table;
`<div class="category">
<ul class="list-group"">${table}</ul>
</div>
`
</>
When you dynamically generate html and we cannot pass objects directly from the generation logic to the runtime, however we can easily hookup callbacks that pass identifiers or index values to our javascript functions that at runtime can use the value to lookup the original object reference.
This example extends the original post and uses the index:
let table = ``;
let viewData = [{name: 'Item1', Id: 1},{name: 'Item2', Id: 2}];
viewData.forEach((category, indx) => {
table += `
<div >
<li key="${indx}" onclick="(categoryClicked(${indx}))" class="list-group-item" >
${category.name}
</li></div>
`
});
var evento = document.getElementById('evento');
evento.innerHTML = table;
`<div class="category">
<ul class="list-group"">${table}</ul>
</div>
`;
var categoryClicked = function (indx) {
// passed in index
console.log(indx);
// lookup the category from the viewData so we can access other properties
let category = viewData[indx];
console.log(category);
}
Using the index is generally not recommended, index is a volatile link that can easily be affected by sorting, filtering or other mutating operations against the array source. Your solution will be more robust if you use an identifier from the element in the array: fiddle
let table = ``;
let viewData = [{name: 'Item1', Id: 1},{name: 'Item2', Id: 2}];
viewData.forEach((category) => {
table += `
<div >
<li key="${category.Id}" onclick="(categoryClicked(${category.Id}))" class="list-group-item" >
${category.name}
</li></div>
`
});
var evento = document.getElementById('evento');
evento.innerHTML = table;
`<div class="category">
<ul class="list-group"">${table}</ul>
</div>
`;
var categoryClicked = function (id) {
// passed in index
console.log(id);
// lookup the category from the viewData so we can access other properties
let category = viewData.find(cat => cat.Id === id);
console.log(category);
}
If you find yourself extensively generating code like this, you should transition over to a javascript templating framework like Handlebars.js, or something more robust like AngularJS/ReactJS/VuewJS

How to display elements data stored in a javascript array as list elements in the DOM

I am a newbie at web development. I am trying to display data that is being stored in javascript array, inside an unordered list as list elements.
I have tried looping through the elements in the array and display them one at a time using for loops but its not working
let linksArray = [] // array to store link leads while browsing
let inputEl = document.getElementById("input-el") // to get a hold on the input element from the dom
let displayEl = document.getElementById("display_link-el")
//function to save links inputs into linksArray
function save(params) {
linksArray.push(inputEl.value)
console.log(linksArray);
localStorage.setItem("mylinks", JSON.stringify(linksArray))
inputEl.value = ""
displayEl.textContent = linksArray
}
//function to conver linksArray to a list element in the DOM
function convetToListli(linksArray) {
for (let i = 0; i < linksArray.length; i++) {
let links = "<li>"
linksArray[i]
" </li>"
}
}
<input id="input-el" title="lead" placeholder="input weblink" type="text">
<button id="input-btn" onclick="save()">SAVE </button>
<button id="del-btn" ondblclick="delLeads()">DELETE</button>
<div>
<div>
<ul id="display_link-el"></ul>
</div>
<div>
<ul id="log_link-el"></ul>
</div>
</div>
I have added small correction to your script
function save(params) {
linksArray.push(inputEl.value)
console.log(linksArray);
inputEl.value=""
displayEl.innerHTML = convetToListli(linksArray)
}
//function to conver linksArray to a list element in the DOM
function convetToListli(linksArray) {
var links = ""
for (let i = 0; i < linksArray.length; i++) {
links= links + "<li>"+linksArray[i]+" </li>"
}
return links
}
This is just for example purchase
NOTE: Make sure to filter the input field while using innerHTML because it will leads to XSS
You should learn basic DOM manipulations. Here's one possible solution for your question
const list = document.querySelector('.list');
const links = ['link 1', 'link 2', 'link 3'];
links.forEach(link => {
let item = document.createElement('li');
item.textContent = link;
list.appendChild(item)
})
<ul class="list"></ul>

How can I select the id of the outermost element inside a parent element?

For example is I have a <div>, so inside my <div> i have some elements with id such as <label>, <span> and <p> the first element that occurs on my code is the <p>
<div id = 'cont' class = 'inc'>
<p id = '1' class = 'box'>
<label id ='aa' class = 'innerbox'><span id = 'aaa' class = 'innerboxs'></span></label>
</p>
<p id = '2' class = 'box'>
<label id ='aa' class = 'innerbox'><span id = 'aaa' class = 'innerboxs'></span></label>
</p>
<p id = '3' class = 'box'>
<label id ='aa' class = 'innerbox'><span id = 'aaa' class = 'innerboxs'></span></label>
</p>
</div>
Base on the example above, after the <div>, <p> is it's very first child element that occurs. Let's assume that I want to get their ID through this code.
function checkContents(){
var output = "";
var elements = document.querySelectorAll('.inc [id]'),
ids = Array.prototype.map.call(elements, function(element) {
return element.id;
});
output = 'ids = ' + JSON.stringify(ids, null, ' ');
alert(output);
}
This function outputs all the id inside the <div> with the inc class. I just want to get the id of the <p> with the classname of box, how can I get it?
If you're sure, there will only be <p> elements inside the div.inc
then you can simply do
var elements = document.querySelectorAll('.inc p');
If you're not sure what are the first level elements, then you can simply use the selector to select only the immediate children like
var elements = document.querySelectorAll('.inc > *'),
Replace this line
var elements = document.querySelectorAll('.inc [id]'),
with:
var elements = document.querySelectorAll('.inc>*'),
Here is a plunkr for it
Replace following line
var elements = document.querySelectorAll('.inc [id]')
with
var elements = document.querySelectorAll('.inc p[id]'),

Categories

Resources