ReactJs force input focus on div button click not working - javascript

I'm working on a modal in react where I have to click a button outside an input element and focus the input element and change the value. I set the input element to be disabled on default and for the edit button to remove the disabled property and then focus the element. the element is not getting visible focused neither is the disabled property being removed. It looks like it happens in a split second and then returns back to normal because whenever I check if the element is being focused on my console it displays true but It's not being visible focused.
below is my code
EDIT FUNCTION
const [editState,setEditState] = useState(null)
const editCatName = (e,id)=>{
e.stopPropagation();
setEditState({...editState,id: categories[id].id})
setActiveButton('editcatname');
let row = document.querySelectorAll('.cat-row')[id].querySelector('input');
console.log('row',row)
row.classList.remove('pointer');
row.value='Row value set'
row.hasAttribute('disabled') && row.toggleAttribute('disabled')
row.focus();
console.log(row.value)
}
const [activeButton,setActiveButton] = useState('newproduct');
const ProductCategoryModal = ()=>{
return(
<div
onClick={()=>{setCategoryModal(false)}}
className="_modal fixed " style={{zIndex:'100'}} >
<div
onClick={e=>e.stopPropagation()}
className='wytBg boxRad paddBoth sectPad relative'>
<div>
<div className="flexBtw">
<h3 className="head flexAl">Product Categories</h3>
<div className='head'> <AiOutlinePlus/> </div>
</div>
</div>
<GridStyle className='nestM' gridp='45% 55%' gap='0em'>
<Scrolldiv className='' measure='300px'>
{
categories && categories.length?
categories.map((ctg,key)=>
ctg.name !=='Others' &&
<div key={key}
onClick={(e)=>
fixCategoryDetail(ctg.id,e)
}
className={`cat-row cursor rowws flexBtw ${ key===0 && 'rows-
top'}`}>
<div>
<input
defaultValue={ctg.name}
// disabled
style={{maxWidth:'180px'}}
className={'categoryInput pointer '+ key}
onChange={e=>setEditState({
id:ctg.id,
value:e.target.value
})}
onBlur={e=>{
e.target.value=ctg.name
}}
/>
{/* {ctg.name} */}
</div>
<div className="smallflex hashEdit">
<div>
<BiEditAlt
className='cursor'
FUNCTION TO FOCUS ELEMENT IS HERE
onClick={e=>editCatName(e,key)}
/>
</div>
{
!products.find(prod=>prod.category ===ctg.id) &&
<div className='hash'> <CgClose className='cursor'/> </div>
}
</div>
</div>
):null
}
</Scrolldiv>
<Scrolldiv measure='300px' className='secondRow paddBoth'>
{
categoryDetail.length?
<div className=" search flexC">
<div>
<SearchInputBox
icon={ <CgSearch style={{width:30}} />}
padLeft={'10px'}
className='searchInput smalltxt'
inputPadding='0.5em 0.6em'
// onchange={filterByStarts}
iconPosition
summary='Type or search a product'
options=
{products.filter(prod=>
prod.category===3).map(prod=>prod.name)}
inputClassName={'searchInput smalltxt'}
pad='0'
/>
<div className="nestM flex">
<div measure='150px' >
{
categoryDetail.length?
categoryDetail.map((ctg,key)=>
ctg.category !== 3 &&
<div key={key} className=
{`doubleflex flexBtw smalltxt
itemunits ${key!==0 &&
'smallM'} `}>
<div>{ctg.name}</div>
<div>
<CgClose onClick=
{()=>removeProductFromCategory
(ctg.id,ctg.name)}
className='cursor'/>
</div>
</div>
):null
}
</div>
</div>
</div>
</div>
:null
}
</Scrolldiv>
</GridStyle>
<div className="section flexC">
<button style={{maxWidth:'70%'}}
onClick={()=>
activeButton==='newproduct'?removeProductFromCategory():
activeButton==='addcategory'?createNewCategory():
editCategoryName()}
className="submit-button category-submit">
Update
</button>
</div>
</div>
</div>
)
}

Related

render specific text based on Conditional statement

I have the following JSON
{"location":"2034","type":"Residential","price":400000,"address":"123 Fake Street","suburb":"Maroubra","historical_DAs":0,"description":"Residential","property_ID":1},
{"location":"2036","type":"Commercial","price":475000,"address":"123 Fake Street","suburb":"Coogee","historical_DAs":10,"description":"Government","property_ID":2},
{"location":"2035","type":"Food & Bev","price":56000,"address":"123 Fake Street","suburb":"Clovelly","historical_DAs":3,"description":"Residential","property_ID":3},
{"location":"2031","type":"Education","price":69070,"address":"123 Fake Street","suburb":"Randwick","historical_DAs":7,"description":"Government","property_ID":4},
{"location":"2036","type":"Education","price":69070,"address":"123 Fake Street","suburb":"Randwick","historical_DAs":7,"description":"Government","property_ID":5}
I want to render different images based upon the description field (currently trying to just get text to render correctly atm.)
What I have tried so far:
function TypeImages({ description }) {
function Residential(props) {
return <div>
<h1>Image 1</h1>
</div>;
}
function Government(props) {
return <div>
<h1>Image 2 </h1>
</div>;
}
function TypeImage(props) {
if (description === 'Residential') {
return <Residential />;
} else
return <Commercial />;
}
return (
<div>
<div>
<div className="hidden lg:inline-flex mb-1 px-9">
<TypeImage/>
<div>
</div>
</div>
</div>
</div>
);
}
export default TypeImages;
This isn't working as what is rendered is all 'Image 2' even though there should be some 'Image 1'
Any suggestions on the most efficient way to achieve this?
Thanks!
You can do by many ways,
You need to make sure or check if description has value, if not you probably get unexpected behaviors
Sandbox Example: https://codesandbox.io/s/stupefied-water-sc4o5h?file=/src/App.js
Using ternary conditional statements
return (
<div>
<div>
<div className="hidden lg:inline-flex mb-1 px-9">
{/* Doing this */}
{description === "Residential" ? <Residential /> : <Government /> }
<div>
</div>
</div>
</div>
</div>
);
Doing the way that you was working
function TypeImage() {
if (description === 'Residential') {
return <Residential />;
}
return <Government/>;
}
return (
<div>
<div>
<div className="hidden lg:inline-flex mb-1 px-9">
<TypeImage/>
<div>
</div>
</div>
</div>
</div>
);
Doing this another way using conditional inline
return (
<div>
<div>
<div className="hidden lg:inline-flex mb-1 px-9">
{description === "Residential" && <Residential /> }
{description === "Government" && <Government/> }
<div>
</div>
</div>
</div>
</div>
);

React - Prevent child re-rendering in map

I have a re-render issue with a slider which appears in every element from a map.
const Attractions = () => {
const [slide, setSlide] = useState(0)
const handleSlider = (direction) => {
if(direction === "right"){
setSlide(slide + 1)
}else{
setSlide(slide - 1)
}
}
const translation = slide * - 110
return (
<div className="attractions">
<Navbar />
<Header nav={"attractions"}/>
<div className="attractionsContainer">
<div className="attractionsWrapper">
<div className="left">
</div>
<div className="right">
{attractionList.map(attraction => (
<div className="attractionWrapper" key={attraction.id}>
<div className="top">
<div className="topLeft">
<img src="https://holidaystoswitzerland.com/wp-content/uploads/2019/09/Lauterbrunnen.jpg.webp" alt="" className="avatarImg"/>
</div>
<div className="topRight">
<div className="title">{attraction.name}</div>
<div className="location"><LocationOnOutlinedIcon/>{attraction.location.city}, {attraction.location.country}</div>
</div>
<div className="moreInfo">
<MoreVertOutlinedIcon/>
</div>
</div>
<div className="middle">
<div className="sliderWrapper">
{slide > 0 &&
<div className="left" onClick={()=>handleSlider("left")}>
<ArrowBackIosNewOutlinedIcon style={{fontSize: "30px"}}/>
</div>
}
<div className="slider" style={{transform: `translateX(${translation}%)`}}>
{attraction.img.map(img =>(
<img src={img} alt="" />
))}
</div>
{slide < 2 &&
<div className="right" onClick={()=>handleSlider("right")}>
<ArrowForwardIosOutlinedIcon style={{fontSize: "30px"}}/>
</div>
}
</div>
</div>
<div className="bottom">
<div className="interactions">
<FavoriteBorderOutlinedIcon className="actionBtn"/>
<ChatBubbleOutlineOutlinedIcon className="actionBtn"/>
<CheckCircleOutlineRoundedIcon className="actionBtn"/>
<AddCircleOutlineOutlinedIcon className="actionBtn" />
</div>
<div className="description">
{attraction.description}
</div>
<div className="comments">
{attraction.comments.map(comment =>(
<div className="commentItem">
<h4>{comment.user}</h4>
<span>{comment.comment}</span>
</div>
))}
</div>
</div>
</div>
))}
</div>
</div>
</div>
<Footer />
</div>
)
}
When i get more elements from the attractionList array, whenever i click on the left or right arrow to go to the next slide, all of the sliders from the list will do the same. I figured out that i should use something so that the slide is set only based on the item from the map, but honestly i have no idea how.
If you want them to behave differently, then the attraction object should have its own slide variable and setSlide method. That way you can just put:
onclick = {() => attraction.setSlide(attraction.slide + 1)}

Add popup in every item of flatlist in React

I would like to add a popup form in each item in the Flatlist, and the item is actually a card.
My problem is that every time, I clicked the button, the popup shows but, when my mouse moves out of the card, instead of showing the original one, it shows another popup whose parent is the whole page.
I know the problem should be that I need not set the variable setPopup properly. But I don't know how to fix it.
When my mouse is on the card:
enter image description here
When my mouse is out of the card, the popup will move up and its position will be based on the whole page:
enter image description here
Thank you!
This is my code.
const [buttonPopUp, setButtonPopUp] = useState(undefined);
const renderItem = (item, index) => {
return(
<Card key={index} style={{width: '20rem'}}>
<CardImg className='galleryPics' top src={galleryPic.img} alt="..."/>
<CardBody>
<PopUpEditGallery
gallery={item}
index = {index}
trigger={buttonPopUp}
setTrigger={setButtonPopUp}
>
Edit
</PopUpEditGallery>
<CardTitle className='cardTitle'>{item.title}</CardTitle>
<CardText className='cardText'>{item.description}</CardText>
<Button className="btn-round btn-icon" color="primary" size='sm' onClick={()=> setButtonPopUp(index)}>Edit</Button>
</CardBody>
</Card>
);
}
return (
<div>
<div>
<Header/>
</div>
<div className="container">
<div className="row">
<div className='col-7'>
<ul>
<FlatList
list={values.gallery}
renderItem={renderItem}/>
</ul>
</div>
</div>
</div>
</div>
)
code for popup
return (props.trigger != undefined) ? (
props.trigger == props.index &&
<div className='popup'>
<div className='popupInner'>
<form onSubmit={handleSubmit(onSubmit)}>
<FormGroup>
<Label>Title</Label>
<Input
type="text"
placeholder={prev.title}
onChange={val => props.setTitle(val.target.value, prev.idx)}
/>
</FormGroup>
<Button className="btn-round btn-icon" color="primary" size='sm'>
Submit
</Button>
<Button className="btn-round btn-icon" color="default" size='sm'>
Cancel
</Button>
</form>
</div>
</div>
): "";

How to blur out an entire webpage when a button is clicked

I'm setting up a one-page website with react.js, html, and scss. I am struggling to have the entire website have a blur effect or fade when a button is clicked (this will be later used for loading animations). What commands can I use to get this blur when a button is pressed?
render() {
return (
<div className="App">
<div className="top-bar">
<div className="title">poem</div>
<img className="logo" src="./logo.png" />
</div>
<div className="container">
<div className="sloganLineOne">Poem Theme</div>
<div className="sloganLineTwo">Detector</div>
<textarea
className="inputField"
placeholder="Please Enter Your Poem Here..."
/>
<button className="button" onClick={this.fadeOut}>
Enter
</button>
<img className="leftTriangle" src="./leftSideTriangle.png" />
<img className="rightTriangle" src="./rightSideTriangle.png" />
</div>
</div>
)
}
fadeOut = () => this.setState({ fadingOut: true })
}
I expect the entire page to be blurred or look like it when the button is clicked.
All you have to do is apply the style to your parent div and you should be good to go! Give this a shot
class App extends React.Component {
state = { fadingOut: false }
fadeOut = () => this.setState({fadingOut: true});
render() {
return (
<div className="App" style={this.state.fadingOut ? {filter: 'blur(2px)'} : undefined }>
<div className="top-bar">
<div className="title">
poem
</div>
</div>
<div className="container">
<div className="sloganLineOne">Poem Theme</div>
<div className="sloganLineTwo">Detector</div>
<textarea className="inputField" placeholder="Please Enter
Your Poem Here..."></textarea>
<button className="button" onClick={this.fadeOut}>Enter</button>
<img className="leftTriangle" src="./leftSideTriangle.png"/>
<img className="rightTriangle" src="./rightSideTriangle.png"/>
</div>
</div>
);
}
}
See it in action!

Pass value to a modal in jsx map

I have a map that render few items. How can I pass params like name of the item, id of the item etc to the modal component?
render(){
return(
<div>
<Modal
isOpen={this.state.OpenDeleteModal}
confirmationTitle={`Delete item`}
confirmationCancel={'No'}
confirmationSuccess={'Yes'}
closeModal={this.closeModal}
successModal={this.successModal}
>
<p className="center">Are you sure you want to delete this item?</p>
</Modal>
<div className="wrapper">
{map(items, obj =>
<div key={obj._id} className="panel-body">
<div className="row">
<h2 className="title">{obj.name}</h2>
<a onClick={()=> this.setState({OpenDeleteModal:true})}>Delete</a>
</div>
</div>
)}
</div>
</div>
)
}
I only can think of put the obj._id in the tag as custom attribute and when user click on delete it change the state of the selectedItem, pass it through props.
One simple solution is to remember for which item you have opened the modal. Something like below. Set the selected item when you open the modal. During delete, fetch it from state and delete it.
render(){
return(
<div>
<Modal
isOpen={this.state.OpenDeleteModal}
confirmationTitle={`Delete item`}
confirmationCancel={'No'}
confirmationSuccess={'Yes'}
closeModal={this.closeModal}
successModal={this.successModal}
>
<p className="center">Are you sure you want to delete this item?</p>
</Modal>
<div className="wrapper">
{map(items, obj =>
<div key={obj._id} className="panel-body">
<div className="row">
<h2 className="title">{obj.name}</h2>
<a onClick={()=> this.setState({OpenDeleteModal:true, selectedItem: obj._id})}>Delete</a>
</div>
</div>
)}
</div>
</div>
)
}
UPDATE: Make sure to clear the selectedItem after you close the modal.
A modal can access the state of the react component, you can store the information of the selected link in state
storeInformation(item) {
this.setState({OpenDeleteModal:true,
selectedId: item.id
selectedName: item.name
})
}
render(){
return(
<div>
<Modal
isOpen={this.state.OpenDeleteModal}
confirmationTitle={`Delete item`}
confirmationCancel={'No'}
confirmationSuccess={'Yes'}
closeModal={this.closeModal}
successModal={this.successModal}
>
<p className="center">Are you sure you want to delete this item?</p>
<div>Name is: {this.state.selecteName}</div>
</Modal>
<div className="wrapper">
{map(items, obj =>
<div key={obj._id} className="panel-body">
<div className="row">
<h2 className="title">{obj.name}</h2>
<a onClick={()=> this.storeInformation(obj)}>Delete</a>
</div>
</div>
)}
</div>
</div>
)
}

Categories

Resources