How to add border to a active div? - javascript

I want to make a border when the user set a div active.
I tried to add hover, selected and active, but it did not work.
This is the part that user will select
{this.state.fields.map((fields, k) =>
<div key={k} onClick={() => this.setState({
activeFields: fields
})}>
<div className="detailsPage-details " >
{fields.map((field) =>
<p key={k}>
{field.value}: {field.key}
</p>
)}
</div>
</div>
)}
How can I do that?

Your fields should have a unique field so that you could check which field was set to active, you could use the index of the array but it is not preferred as could lead to bugs.
{this.state.fields.map((field, k) =>
<div className={this.state.activeField===field.id?"active-div":""} key={k} onClick={() => this.setState({
activeField: field.id
})}>
<div className="detailsPage-details " >
{fields.map((field) =>
<p key={k}>
{field.value}: {field.key}
</p>
)}
</div>
</div>
)}

Related

Create multiple buttons React JS

I have the ability to render my single button with all my options inside of the one button like this:
What I want to do is separate these into individual buttons
My code is as follows (the first button is the one in question, how do I make them individual?)
function Filters({ filter, setFilter, location }) {
return (
<div className="bg-transparent outline-none text-sm text-gray-600 placeholder-grey-400">
<div className="pl-2 pr-2 gap-3">
<Button
colorScheme="teal"
size="xs"
onClick={(e) => {
setFilter({
...filter,
search: e.target.value,
});
}}
>
{locations.map((item, index) => (
<text>
<option key={index} value={item.location}>
{item.location}
</option>
</text>
))}
</Button>
<Button
colorScheme="teal"
size="xs"
onClick={(e) => {
setFilter({
...filter,
search: e.target.value,
});
}}
>
ALL
</Button>
</div>
</div>
);
}
export default Filters;

Hide dropdowns in loop on click outside

I have an array of values which would render a list with a dropdown menu.
I would show/hide the dropdown on click of an element.
projectData.map(project => (
<div>
<div>{project.name}</div>
<div
onClick={() => setDropdownId((prevState) => (
prevState === project.id ? null : project.id)
)}
>
Show
</div>
{dropdownId === project.id && (
<ul className="dropdown">
<li>option</li>
</ul>
)}
</div>
))
How can I hide the opened dropdown on outside click?
I tried with ref but is not working as expected as the elements are in a loop.
Use onBlur to trigger changes when loosing focuse
handleBlur = (e) => {
// add you code here
}
projectData.map(project => (
<div>
<div>{project.name}</div>
<div
onBlur={handleBlur}
onClick={() => setDropdownId((prevState) => (
prevState === project.id ? null : project.id)
)}
>
Show
</div>
{dropdownId === project.id && (
<ul className="dropdown">
<li>option</li>
</ul>
)}
</div>
))

Reactjs filter where result is zero

I want to have text on the page change when no items from a mapped array are showing.
I am showing a list of questions, but if a question is "answered" (a boolean of answered: true), it is not mapped.
I'm trying to figure out the best way to determine if every item in the array has answered: true, and then change text on the page accordingly. Is it possible to use filter for this when I need a function that checks for no results coming back?
The page shows a list to the left, and the text "please click on a question" to the right. When a question is selected, it replaces "please click on a question" with information about the selected question. But when there are no questions, I want "please click on a question" to show something like "There are currently no questions to answer".
this.state = {
questions: [],
currentQuestion: null,
currentIndex: -1,
searchQuestion: "",
wanttodelete: false
};
{questions &&
questions.map((question, index) => (
<div key={index}>
{!question.answered &&
<li
className={
"list-group-item " +
(index === currentIndex ? "active" : "")
}
onClick={() => this.setActiveQuestion(question, index)}
key={index}
>
<p>
{question.question}
</p>
</li>
}
</div>
))}
</ul>
</div>
<div className="col-lg-8 question-area">
{currentQuestion ? (
<div>
<h4>
<FormattedMessage
id="question-list.questionHeader"
defaultMessage="Question"
description="Question header"/>
</h4>
<div>
<label>
<strong>Question:</strong>
</label>{" "}
{currentQuestion.question}
</div>
<div>
<label>
<strong>Category:</strong>
</label>{" "}
{currentQuestion.categoryId}
</div>
<div>
<label>
<strong>Status:</strong>
</label>{" "}
{currentQuestion.answered ? "Answered" : "Awaiting answer"}
</div>
<Link
to={"/questions/" + currentQuestion.id}
className="badge badge-warning"
>
Answer this question
</Link>
</div>
) : (
<div>
<p>Please click on a Question...</p>
</div>
)}
</div>
</div>
</div>
</div>
);
}
}
const nothingToAnswer = questions.every(question => question.answered);

Cards inside the grid-container: each child in a list should have a unique "key" prop

What I`m doing wrong?It also says: "Check the render method of Card" , which is here:
<div className="grid-container">
{pokemonData.map((pokemon, i) => {
console.log(pokemon.id) // unique numbers are here
return <Card key={pokemon.id} pokemon={pokemon} />
})}
</div>
Card component itself:
function Card({ pokemon }) {
return (
<div className="card">
<div className="card__image">
<img src={pokemon.sprites.front_default} alt="Pokemon" />
</div>
<div className="card__name">
{pokemon.name}
</div>
<div className="card__types">
{
pokemon.types.map(type => {
return (
<div className="card__type" style={{backgroundColor: typeColors[type.type.name]}}>
{type.type.name}
</div>
)
})
}
</div>
<div className="card__info">
<div className="card__data card__data--weight">
<p className="title">Weight:</p>
<p>{pokemon.weight}</p>
</div>
<div className="card__data card__data--height">
<p className="title">Height:</p>
<p>{pokemon.height}</p>
</div>
<div className="card__data card__data--ability">
<p className="title">Abilities:</p>
{/* {console.log(pokemon.abilities)} Temporary for dev puprose */}
{pokemon.abilities.map(ability => <p>{ability.ability.name}</p>
)}
</div>
</div>
</div>
);
}
export default Card;
You can use the index of the array may be your data is having some kind of duplicate. It is recommended that you pass a key prop whenever you are returning a list.
<div className="grid-container">
{pokemonData.map((pokemon, i) => {
console.log(pokemon.id) // unique numbers are here
return <Card key={i} pokemon={pokemon} />
})}
</div>
Equally, check this segment of card components.
{
pokemon.types.map((type,i) => {
return (
<div key={i} className="card__type" style={{backgroundColor:
typeColors[type.type.name]}}>
{type.type.name}
/div>
)
})
}
And
<div className="card__data card__data--ability">
<p className="title">Abilities:</p>
{/* {console.log(pokemon.abilities)} }
{pokemon.abilities.map((ability, i) => <p key={i}>{ability.ability.name}
</p>
)}
</div>
Previous answer will solve your problem. However, for your info, I would also like to add here.
For React a key attribute is like an identity of a node/element/tag which helps React to identify each item in the list and apply reconciliation correctlyon each item. Without a key React will render your component but may cause issue when you re-order your list.
React recommends to use id of the data instead of index number. However, if your list does not re-orders/ sorts or do not have id then you can use index.
You can read more here:
https://reactjs.org/docs/lists-and-keys.html
Change this:
<div className="card__types">
{
pokemon.types.map(type => {
return (
<div className="card__type"
style={{backgroundColor:typeColors[type.type.name]}}
>
{type.type.name}
</div>
)
})
}
</div>
to:
<div className="card__types">
{
pokemon.types.map((type, key) => {
return (
<div key={key} className="card__type"
style={{backgroundColor:typeColors[type.type.name]}}
>
{type.type.name}
</div>
)
})
}
</div>
and:
{pokemon.abilities.map(ability => <p>{ability.ability.name}</p>
to:
{pokemon.abilities.map((ability,key) => <p key={key} >{ability.ability.name}</p>

Delete a <div> onClick in React

I would like to delete a search result by clicking on the X icon on the individual card.
The search returns 10 recipes from the API, generating 10 divs. How would I go about removing individual divs onClick of the icon whilst keeping the other divs? Essentially just a remove search result button.
return (
<div className='App'>
<form onSubmit={getSearch} className="search-form">
<InputGroup>
<InputGroupAddon addonType="prepend">
<InputGroupText><FontAwesomeIcon icon={faSearch} /></InputGroupText>
</InputGroupAddon>
<Input className="search-bar" type="text" placeholder="Search for recipe..." value={search} onChange={updateSearch} />
</InputGroup>
<Button color="primary" size="sm" className="search-button" type="submit">Search</Button>
</form>
<div className="recipes">
{recipes.map(recipe => (
<Recipe
key={recipe.recipe.label}
title={recipe.recipe.label}
theUrl={recipe.recipe.url}
image={recipe.recipe.image}
ingredients={recipe.recipe.ingredients}
source={recipe.recipe.source}
healthLabels={recipe.recipe.healthLabels}
servings={recipe.recipe.yield} />
))}
</div>
</div>
const Recipe = ({ title, theUrl, image, ingredients, source, healthLabels, servings }) => {
return (
<div className={style.recipe}>
<FontAwesomeIcon className={style.delete} icon={faTimes} />
<h3 >{title}</h3>
<Badge className={style.badge} color="primary">{source}</Badge>
<p>Serves: <Badge color="primary" pill>{servings}</Badge></p>
<img src={image} alt='food' />
<ol className={style.allergens}>
{healthLabels.map(healthLabel => (
<li>{healthLabel}</li>
))}
</ol>
<div className={style.ingr}>
<ol>
{ingredients.map(ingredient => (
<li>{ingredient.text}</li>
))}
</ol>
<Button className={style.button} outline color="primary" size="sm" href={theUrl} target="_blank">Method</Button>
</div>
<div className={style.info}>
<div className={style.share}>
<WhatsappShareButton url={theUrl}><WhatsappIcon round={true} size={20} /></WhatsappShareButton>
<FacebookShareButton url={theUrl}><FacebookIcon round={true} size={20} /></FacebookShareButton>
<EmailShareButton url={theUrl}><EmailIcon round={true} size={20} /></EmailShareButton>
</div>
</div>
</div>
);
}
Simply update the recipes array and React will update the HTML.
I'm not sure where recipes comes from, but if you set an onClick on, say, <Recipe label="x"> that deletes the corresponding recipe element from recipes, then React should no longer render that recipe.
That should be easy. Here's one way:
add onClick to this
<FontAwesomeIcon onClick={deleteRecipe} className={style.delete} icon={faTimes} />
pass a reference of the function that deletes the recipe.
deleteRecipeHandler = (id) => {
// filter your recipes here such that the new recipes array doesn't contain the recipe
// with the id you're getting here.
// Change the below code how you need
const newRecipes = oldRecipes.filter(recipe => {
return recipe.id !== id;
});
}
{recipes.map(recipe => (
<Recipe
key={recipe.recipe.label}
deleteRecipe={this.deleteRecipeHandler.bind(this,recipe.recipe.id)}
title={recipe.recipe.label}
theUrl={recipe.recipe.url}
image={recipe.recipe.image}
ingredients={recipe.recipe.ingredients}
source={recipe.recipe.source}
healthLabels={recipe.recipe.healthLabels}
servings={recipe.recipe.yield} />
))}
since you're destructuring your props you can use
const Recipe = ({ title, theUrl, image, ingredients, source, healthLabels, servings, deleteRecipe }) => {
return (
<div className={style.recipe}>
<FontAwesomeIcon onClick={deleteRecipe} className={style.delete} icon={faTimes} />

Categories

Resources