This is bugging me quite a bit. I hope someone can help me with it. I'm doing this in React.
Here is the data (objects that have an array inside):
{
"Susan": {
"likes": [
"shopping",
"skiing",
"surfing"
],
"hates": [
"cycling",
"reading",
"cleaning"
]
},
"Andrew": {
"likes": [
"driving",
"hiking",
"coding"
],
"hates": [
"dancing",
"running",
"cleaning dishes"
]
}
}
Now, in this case, I would like to display/map both arrays ("likes" and "hates") based on user choosing "Susan" or "Andrew". I just can't seem to logical connect this.
Let's say user input is a variable:
let input = "Susan"
I have something like:
Object.values(data).filter((val) => {
if(input === val) {
return val;
}
}).map((obj) => {
return (
<div>
<p> {obj.likes} </p>
<p> {obj.hates} </p>
</div>
);
})
I know there has to be some kind of binding with the keys, but I don't know how to do that.
Your help is very much appreciated!
CodePudding user response:
I think you may be overcomplicating this if I'm not misunderstanding the question.
data['Susan']
will get you an entry with the 'likes' and 'hates' arrays. You can use it like this:
const data = {
"Susan": {
"likes": [
"shopping",
"skiing",
"surfing"
],
"hates": [
"cycling",
"reading",
"cleaning"
]
},
"Andrew": {
"likes": [
"driving",
"hiking",
"coding"
],
"hates": [
"dancing",
"running",
"cleaning dishes"
]
}
}
const createDiv = (name) => {
let entry = data[name];
return (
<div>
<p> {entry.likes} </p>
<p> {entry.hates} </p>
</div>
);
}
let element = createDiv('Susan');
CodePudding user response:
You should filter your data as entries i.e. Object.entries
so that you retain the object key (name) and the value (likes and dislikes).
I added a debounce to the input field so that entries only get filtered/rendered when the user stops typing.
const
filteredResults = document.querySelector('#filtered-results'),
searchTerm = document.querySelector('#search-term');
const render = () => {
const filtered = searchTerm.value.trim().length
? Object.entries(data)
.filter(([key, value]) => searchTerm.value.includes(key))
: Object.entries(data);
filteredResults.innerHTML = `
<ul >
${filtered.map(([key, { likes, hates }]) => {
return `
<li>
<h1>${key}</h1>
<h2>Likes</h2>
<ul >
${likes.map(like => `<li>${like}</li>`).join('')}
</ul>
<h2>Hates</h2>
<ul >
${hates.map(hate => `<li>${hate}</li>`).join('')}
</ul>
</li>
`;
}).join('')}
</ul>
`;
};
const main = () => {
render();
searchTerm.addEventListener('keyup', handleKeyUp);
};
const debounce = (callback, wait) => {
let timeoutId = null;
return (...args) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(() => {
callback.apply(null, args);
}, wait);
};
};
const handleKeyUp = debounce((event) => {
render();
}, 500);
const data = {
"Susan": {
"likes": [ "shopping", "skiing", "surfing" ],
"hates": [ "cycling", "reading", "cleaning" ]
},
"Andrew": {
"likes": [ "driving", "hiking", "coding" ],
"hates": [ "dancing", "running", "cleaning dishes" ]
}
};
main();
*, *:before, *:after {
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
h1, h2 {
margin: 0;
padding: 0;
font-weight: normal;
}
body {
display: flex;
flex-direction: column;
align-items: center;
padding: 1rem;
}
.entries {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 0;
padding: 0;
list-style-type: none;
gap: 1rem;
padding: 0.5rem;
}
.entries > li {
display: flex;
flex-direction: column;
min-width: 20rem;
background: #EEE;
border: thin solid #AAA;
padding: 0.5rem;
}
.entries li h1 {
font-weight: bold;
font-size: 1.25rem;
margin: 0.25rem 0 0.5rem 0;
}
.entries li h2 {
font-weight: bold;
font-size: 1rem;
margin: 0.125rem 0 0.25rem 0;
}
.sublist {
margin: 0;
padding: 0;
list-style-type: none;
}
.sublist > li {
display: inline-block;
margin-right: 0.5rem;
padding: 0.25rem;
border: thin solid #AAA;
}
<input type="text" id="search-term" placeholder="Filter by name" />
<hr />
<div id="filtered-results"></div>