Edit option is opened in every row when clicked - javascript

I am working on an application , where I've to show Edit Popup when click on icon . Now it working fine but problem is whenever I click on row it showing in each individual rows. I want to show single popup with each row not multiple . Now if I click on 5 rows popup showing 5 times I want to show single popup in each individual row
const editToggle = (index) => {
if (index === id) {
setShowModal(true)
}
}
{showModal && (
<div className="card-container">
<div className="container_separator card-container-text">Edit</div>
<div className="container_separator card-container-text">Delete</div>
</div>
)}

Set the id of the row you wish to open in the showModal state, and open the modal if the showModal value is identical to the id:
const [showModal, setShowModal] = useState(-1)
const editToggle = (index) => {
if (index === id) {
setShowModal(id)
}
}
{showModal === id && (
<div className="card-container">
<div className="container_separator card-container-text">Edit</div>
<div className="container_separator card-container-text">Delete</div>
</div>
)}

Related

When I press the icon, I want the matter in the area I stepped on to disappear with React

const [todo,setTodo] = useState([]);
const removeTodo = id => {
const removedArr = [...todo].filter(item => item.id !== id);
setTodo(removedArr);
};
<div className="todoList">
{todo.map((item, index) => (
<div className="todoTarget" key={index}>
<span className="todoSpan">{index+1} - {item}</span>{" "}
<div>
<FaTimesCircle onClick={() => removeTodo(item.id)}/>
</div>
</div>
))}
</div>
My code snippet is like this, when I click on the icon, all the items disappear, not the item in the icon I clicked. What is the reason. I would appreciate your help.
I tried to freeze it with the map function in the arrays and solve it with the id of each item, but they all disappear.
Such things usually happens when you don't have a unique id for every object in the list.
Check if every item in your todo list has a unique id, in case not then add one. should work just fine.
check my example with your code here:
https://codesandbox.io/s/serene-https-pyr1ie?file=/sr

Add animation to filter items on click

I created a filter gallery. I want to animate the filter items every time I click to a buttons. But my codes are not doing it properly. It animates filter items like toggle. If I click on a button first time it animates items, then If I click on another button it shows nothing. After that If I click on another button it animates again. What's wrong with my code? Experts please help me to find out the proper solution. Thanks in advance.
Here is my code:
import React, { useState } from 'react';
import suggestData from '../data/suggest-data.json';
const allCategories = ['All', ...new Set(suggestData.map(item => item.area))];
const Suggest = () => {
const [suggestItem, setSuggestItem] = useState(suggestData);
const [butto, setButto] = useState(allCategories);
const [selectedIndex, setSelectedIndex] = useState(0);
const [anim, setAnim] = useState(false);
const filter = (button) => {
if (button === 'All') {
setSuggestItem(suggestData);
return;
}
const filteredData = suggestData.filter(item => item.area === button);
setSuggestItem(filteredData);
}
const handleAnim = () => {
setAnim(anim => !anim);
}
return (
<div>
<h1>Suggest</h1>
<div className="fil">
<div className="fil-btns">
<div className="fil-btn">
<button className='btn'>Hello</button>
{
butto.map((cat, index) => {
return <button type="button" key={index} onClick={() => { filter(cat); setSelectedIndex(index); handleAnim(); }} className={"btn" + (selectedIndex === index ? " btn-active" : "")}>{cat}</button>
})
}
</div>
</div>
<div className="fil-items">
{
suggestItem.map((item, index) => {
return (
<div className={"fil-item" + (anim ? " fil-item-active" : "")} key={index}>
<h1>{item.name}</h1>
<h2>{item.category}</h2>
<h3>{item.location}</h3>
<h4>{item.type}</h4>
<h5>{item.area}</h5>
</div>
);
})
}
</div>
</div>
</div>
);
}
export default Suggest;
In your handleAnim() function, you are simply toggling the value of anim state. So initially, its value is false and when you click the button for the first time, it is set to true. On clicking the next button, the anim state becomes false because the value of !true is false and hence your animation doesn't work. On next click, becomes true again since !false is true and the toggle continues again and again.
If you want to make your animations work on every click you will need to set the anim state value to true on every button click as below since you seem to depend on the value to set animations. As an alternative, I think it will do just fine if you simply add the animation directly to the enclosing div with class .filter-item instead of relying on states to trigger the animation since after every filter you apply, the elements will be re-rendered and the animation will happen after every re-render.
const handleAnim = () => {
setAnim(true);
}

select a div from a list of divs and toggle class on that div reactjs functional component

I have a functional component in react that receives an array with numeric values.
For each value I build a div and place them next to each other in a flexbox.
When I click on a div I have to select it by adding or removing the class selection-bar-selected which simply changes the color of a bar placed at bottom of the div.
What I did works but it selects all the divs, how can I make it select only the div I clicked?
Here is my code and thanks in advance for the answers.
const [selected, setSelected] = useState(false);
const SelezionaTab = () =>{
selected ? setSelected(false) : setSelected(true);
}
return (
<div className="months-tab">
{props.data.map((v, k) =>
<div className="single" key={k} id={"tab-"+k} onClick={SelezionaTab}>
<div className="single-header">
<p className="mese">{k}</p>
</div>
<div className="single-body">
<div className="value">
<p className="numero-spese">{v.doc} doc.</p>
<p className="importo">{v.val}</p>
</div>
<div className={selected ? "selection-bar selection-bar-selected" : "selection-bar"}>
</div>
</div>
</div>
)}
</div>
)
You need to distinguish which tab is selected in the selected state, so for example you can change its value from being a boolean to a number or string that holds the index or name or id of the currently selected tab(s), so:
const [selected, setSelected] = useState({});
// This is really `ToggleTab` rather than `SelezionaTab`
const SelezionaTab = (tabId = null) => {
setSelected({ ...selected, [tabId]: !selected[tabId] })
}
// in the component
onClick={() => SelezionaTab(k)}
// and the selected class becomes:
<div className={selected[k] ? "selection-bar selection-bar-selected" : "selection-bar"}>
The selected state that you are storing could be the id or index of the element. Then when you loop over the list you only change the class when the id or index matches currently selected.
Right now you are only suggesting that there is something selected, but true/false doesn’t tell you which item in the list.
You are very close otherwise.

How to triggter validation in wizard when cliking on Next button?

In Laravel 8 app which uses vuejs and jquery
I found wizard made with html like :
<div class="content__inner">
<div class="ccontainer overflow-hiddenn">
<!--multisteps-form-->
<div class="multisteps-form">
<div class="multisteps-form__progress">
<button
class="multisteps-form__progress-btn js-active"
type="button"
title="Add Project Info"
>
Project Info
</button>
<button
class="multisteps-form__progress-btn"
type="button"
title="Add Product"
>
Product Details 22222
</button>
<button
class="multisteps-form__progress-btn"
type="button"
title="Project Budget & Diagram"
>
Project Budget & Diagram
</button>
<button
class="multisteps-form__progress-btn"
type="button"
title="Video & Website Link"
>
Video & Website Link
</button>
</div>
<form class="multisteps-form__form">
<!--single form panel-->
<div
class="multisteps-form__panel shadow p-4 rounded bg-white js-active"
data-animation="scaleIn"
>
<!-- <h3 class="multisteps-form__title">Your User Info</h3> -->
<div class="multisteps-form__content">
<div class="row">
<div class="col-xl-4">
<div class="submit-field">
<h5>
Project Name
<span>*</span>
</h5>
<input
type="text"
class="with-border"
id="name_project"
v-model="project.name"
/>
</div>
</div>
<div class="col-xl-4">
<div class="submit-field">
<h5>
Choose Categories
<span>*</span>
</h5>
<b-form-select
class="tzselectpicker"
v-model="project.category"
:options="project_category"
></b-form-select>
</div>
</div>
and inited js function
setStepForm() {
//DOM elements
const DOMstrings = {
stepsBtnClass: "multisteps-form__progress-btn",
stepsBtns: document.querySelectorAll(
`.multisteps-form__progress-btn`
),
stepsBar: document.querySelector(".multisteps-form__progress"),
stepsForm: document.querySelector(".multisteps-form__form"),
stepsFormTextareas: document.querySelectorAll(
".multisteps-form__textarea"
),
stepFormPanelClass: "multisteps-form__panel",
stepFormPanels: document.querySelectorAll(
".multisteps-form__panel"
),
stepPrevBtnClass: "js-btn-prev",
stepNextBtnClass: "js-btn-next"
};
console.log(" setStepForm DOMstrings::");
console.log(DOMstrings);
//remove class from a set of items
const removeClasses = (elemSet, className) => {
elemSet.forEach(elem => {
elem.classList.remove(className);
});
};
//return exect parent node of the element
const findParent = (elem, parentClass) => {
let currentNode = elem;
while (!currentNode.classList.contains(parentClass)) {
currentNode = currentNode.parentNode;
}
return currentNode;
};
//get active button step number
const getActiveStep = elem => {
return Array.from(DOMstrings.stepsBtns).indexOf(elem);
};
//set all steps before clicked (and clicked too) to active
const setActiveStep = activeStepNum => {
//remove active state from all the state
removeClasses(DOMstrings.stepsBtns, "js-active");
//set picked items to active
DOMstrings.stepsBtns.forEach((elem, index) => {
if (index <= activeStepNum) {
elem.classList.add("js-active");
}
});
};
//get active panel
const getActivePanel = () => {
let activePanel;
DOMstrings.stepFormPanels.forEach(elem => {
if (elem.classList.contains("js-active")) {
activePanel = elem;
}
});
return activePanel;
};
//open active panel (and close unactive panels)
const setActivePanel = activePanelNum => {
//remove active class from all the panels
removeClasses(DOMstrings.stepFormPanels, "js-active");
//show active panel
DOMstrings.stepFormPanels.forEach((elem, index) => {
if (index === activePanelNum) {
elem.classList.add("js-active");
setFormHeight(elem);
}
});
};
//set form height equal to current panel height
const formHeight = activePanel => {
const activePanelHeight = activePanel.offsetHeight;
DOMstrings.stepsForm.style.height = `${activePanelHeight}px`;
};
const setFormHeight = () => {
const activePanel = getActivePanel();
formHeight(activePanel);
};
//STEPS BAR CLICK FUNCTION
DOMstrings.stepsBar.addEventListener("click", e => {
//check if click target is a step button
const eventTarget = e.target;
if (
!eventTarget.classList.contains(
`${DOMstrings.stepsBtnClass}`
)
) {
return;
}
//get active button step number
const activeStep = getActiveStep(eventTarget);
//set all steps before clicked (and clicked too) to active
setActiveStep(activeStep);
//open active panel
setActivePanel(activeStep);
});
//PREV/NEXT BTNS CLICK
DOMstrings.stepsForm.addEventListener("click", e => {
const eventTarget = e.target;
//check if we clicked on `PREV` or NEXT` buttons
if (
!(
eventTarget.classList.contains(
`${DOMstrings.stepPrevBtnClass}`
) ||
eventTarget.classList.contains(
`${DOMstrings.stepNextBtnClass}`
)
)
) {
return;
}
//find active panel
const activePanel = findParent(
eventTarget,
`${DOMstrings.stepFormPanelClass}`
);
let activePanelNum = Array.from(
DOMstrings.stepFormPanels
).indexOf(activePanel);
//set active step and active panel onclick
if (
eventTarget.classList.contains(
`${DOMstrings.stepPrevBtnClass}`
)
) {
activePanelNum--;
} else {
activePanelNum++;
}
setActiveStep(activePanelNum);
setActivePanel(activePanelNum);
setTimeout(() => {
var body = $(".dashboard-content-container");
body.stop().animate(
{ scrollTop: 0 },
500,
"swing",
function() {}
);
}, 100);
});
setTimeout(() => {
setFormHeight();
}, 500);
//SETTING PROPER FORM HEIGHT ONLOAD
window.addEventListener("load", setFormHeight, false);
//SETTING PROPER FORM HEIGHT ONRESIZE
window.addEventListener("resize", setFormHeight, false);
//changing animation via animation select !!!YOU DON'T NEED THIS CODE (if you want to change animation type, just change form panels data-attr)
const setAnimationType = newType => {
DOMstrings.stepFormPanels.forEach(elem => {
elem.dataset.animation = newType;
});
};
//selector onchange - changing animation
const animationSelect = document.querySelector(
".pick-animation__select"
);
if (animationSelect != null) {
animationSelect.addEventListener("change", () => {
const newAnimationType = animationSelect.value;
setAnimationType(newAnimationType);
});
}
},
By clicking on "Next" button next step is opened, but I need to validate inputs before moving to next step.
Please any hints how can I make validation here ?
Also is it some library? I searched in net but drowned...
Thanks!
Each wizard view send wizard position in ajax.In backend based on wizard position validate fields .since you know which and all field exist in each wizard view.
For example consider you have 3 wizard steps.
Step 1 has 3 input fields
Step 2 has 2 input fields
Step 3 has 1 input fields
Suppose if you send current step is 1 then you can only validate those fields.
$validations=[
'step1'=>[
//field validation array
],
'step3'=>[
//field validation array
],
'step3'=>[
//field validation array
],
]
then based on request wizard step you can easily fetch validation rules
Validation::make($validations[$request->step]);
Or you can make all fields validate only if exists in the request

React - change state of one button from 100 buttons array, and reset state of all buttons on one click

So, I have 100 mapped buttons from array, something like that
{
buttons.map((button, index) =>
<StyledGameButton
key={index}
value={button}
onClick={this.checkButton}>
{ button < 10 ? `0${button}` : button }
</StyledGameButton>
)
}
I want user to click all the buttons from 0 to 99, so when he click for example 0 the button should change color. I made function checking if he clicked correct button, and if yes then I am addind data-attr to that button (thats how I am changing the color of buttons):
checkButton = e => {
const buttonId = e.currentTarget.getAttribute('value');
const nextButton = this.state.currentButton === null ? 0 : this.state.currentButton + 1;
if (buttonId == nextButton){
this.setState({
currentButton: parseInt(buttonId),
});
if (this.state.currentButton === 99) {
this.gameEnd();
};
e.currentTarget.setAttribute('data-status', 'correct');
}
}
The problem is that I want to make reset button, that will change all buttons to 'unclicked' so I have to delete data-attr from all buttons on one click. How can I do this? Or is there a better solution to manage 'state' of single button without making 100 states?
100 checkboxes demo
use an Array to store the state would be fine.
const list = [...Array(100).keys()].map(x => ({ id: x }));
const App = () => {
const [selected, setSelected] = React.useState([]); // init with empty list
const onChangeHandler = id => () => { // pass index/identify params
selected.includes(id) // check whether been checked
? setSelected(selected.filter(x => x !== id)) // yes, remove
: setSelected([...selected, id]); // no, add
};
const onRemove = () => {
setSelected([]); // remove all, set to empty list
};
return (
<div className="App">
{list.map(item => (
<input
type="checkbox"
key={item.id}
checked={selected.includes(item.id)}
onChange={onChangeHandler(item.id)}
/>
))}
<br />
<button onClick={onRemove}>Remove all</button>
<div>{selected.join(",")}</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

Categories