I want to send only 1 item in Reactjs - reactjs

I have a bit of trouble here, when I do onClick, I hope I can take 1 item, and the handleUpdate() work great
const [langs,setLangs] = useState([]);
function handleUpdate(item){
console.log(item);
}
{langs.map((item, index) => {
<tr key={index}>
//Some code here
<td className='text-primary'
style={{maxHeight: '21px',width: '8%',maxWidth: '300px'}}
onClick={()=>handleUpdate(item)}>
<ModalEditNgonNgu item={item}/>
</td>
</tr>
}
but I don't know why in 'ModalEditNgonNgu' I rendered all items like this
enter image description here
And When I tried to Edit, it can show only the first item, whatever I click.
This is ModalEditNgonNgu:
import '../../css/style.css';
import { useEffect } from "react";
import { useState, useSelector } from "react";
import { ajaxCallGetUrlDemo, ajaxCallPost } from "../libs/base";
import Select from 'react-select'
import { Const_Libs } from "../libs/Const_Libs";
import languagesList from "./languageList/country";
import { get } from 'jquery';
const ModalEditNgonNgu = (props) => {
const { handleGetLanguage } = props;
const [langName, setLangName] = useState("");
const [mainLangs, setMainLangs] = useState([]);
const [mainLang, setMainLang] = useState("");
const [titleLang, setTitleLang] = useState("");
const [describeLang, setDescribeLang] = useState("");
const [authorLang, setAuthorLang] = useState("");
const [rateLang, setRateLang] = useState("");
const [reviewsLang, setReviewsLang] = useState("");
const [translateList, setTranslateList] = useState([]);
const mainLangOptions = [
{ value: 'vi', label: 'Vietnamese' },
{ value: 'en', label: 'English' },
{ value: 'zh', label: 'Chinese' },
{ value: 'ja', label: 'Japanese' },
{ value: 'de', label: 'German' },
];
console.log(props.item);
const handleMainLang=(e)=>{
const getMainLang = e.target.value;
setMainLang(getMainLang);
}
const handleTransList=(e)=>{
const getTransList = e.target.value;
setTranslateList(getTransList);
}
const handleSubmit = () => {
let arr = [{
nameLanguage: langName,
mainLanguage: mainLang,
titleLanguage: titleLang,
descriptionLanguage: describeLang,
authorLanguage: authorLang,
rateLanguage: rateLang,
reviewsLanguage: reviewsLang,
transLanguage: translateList
}]
console.log(arr);
resetData();
props.editLang(arr,props.item.id);
}
const resetData = () => {
setLangName("");
setMainLang("");
setTitleLang("");
setDescribeLang("");
setAuthorLang("");
setRateLang("");
setReviewsLang("");
setTranslateList([]);
}
return (
<>
<button type="button" className="btn btn-primary" data-bs-toggle="modal" data-bs-target="#myModalEditNgonNgu" style={{ fontSize: '14px' }}>
{props.item.language_name}
</button>
<div>
<div className="modal fade" id="myModalEditNgonNgu">
<div className="modal-dialog modal-dialog-centered" style={{ minWidth: '700px' }}>
<div className="modal-content">
<div className="modal-header">
<h4 className="modal-title">Sửa ngôn ngữ</h4>
<button type="button" className="btn-close" data-bs-dismiss="modal" />
</div>
<div className="modal-body">
<form>
<div className="col">
<div className="row-2">
<label htmlFor="name-campaign" className="form-label fs-6 fw-bolder">Tên ngôn ngữ</label>
<input type="text"
className="form-control" id="name-campaign"
placeholder="Nhập tên ngôn ngữ...."
defaultValue={props.item.language_name}
onChange={(e) => setLangName(e.target.value)}
/>
</div>
<div className="row-2">
<label htmlFor="name-campaign" className="form-label fs-6 fw-bolder">Tiêu đề</label>
<input type="text"
className="form-control" id="name-campaign"
placeholder="Nhập tiêu đề...."
defaultValue={props.item.title_lang}
onChange={(e) => setTitleLang(e.target.value)}
/>
</div>
<div className="row-2">
<label htmlFor="name-campaign" className="form-label fs-6 fw-bolder">Mô tả</label>
<input type="text"
className="form-control" id="name-campaign"
placeholder="Nhập mô tả...."
defaultValue={props.item.describe_lang}
onChange={(e) => setDescribeLang(e.target.value)}
/>
</div>
<div className="row-2">
<label htmlFor="name-campaign" className="form-label fs-6 fw-bolder">Tác giả</label>
<input type="text"
className="form-control" id="name-campaign"
placeholder="Nhập tác giả (VD: Author)"
defaultValue={props.item.author_lang}
onChange={(e) => setAuthorLang(e.target.value)}
/>
</div>
<div className="row-2">
<label htmlFor="name-campaign" className="form-label fs-6 fw-bolder">Đánh giá</label>
<input type="text"
className="form-control" id="name-campaign"
placeholder="Nhập đánh giá (VD: Rate)"
defaultValue={props.item.rate_lang}
onChange={(e) => setRateLang(e.target.value)}
/>
</div>
<div className="row-2">
<label htmlFor="name-campaign" className="form-label fs-6 fw-bolder">Lượt đánh giá</label>
<input type="text"
className="form-control" id="name-campaign"
placeholder="Nhập lượt đánh giá (VD: reviews)"
defaultValue={props.item.reviews_lang}
onChange={(e) => setReviewsLang(e.target.value)}
/>
</div>
</div>
<div className="col">
<div className="row-2">
<label htmlFor="name-campaign" className="form-label fs-6 fw-bolder">Ngôn ngữ chính</label>
<Select
onChange={(e) =>setMainLang(e)}
options={mainLangOptions}
/>
</div>
<div className="row-2">
<label htmlFor="name-campaign" className="form-label fs-6 fw-bolder">Những ngôn ngữ dịch</label>
<Select
onChange={(e) =>setTranslateList(e)}
isMulti
isSearchable={true}
options={languagesList}
/>
</div>
</div>
</form>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-success" data-bs-dismiss="modal" onClick={handleSubmit}>Update</button>
<button type="button" className="btn btn-danger" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
</>
);
}
export default ModalEditNgonNgu;
Sorry if I wrote ambiguous, but I want to take correct 'item' whenever I click on the button that have language_name. What should I do?

There is not enough information in your question. I will do my best to help you with your issue in the current context.
There are several issues in your code:
Modal Visibility
When you render the list of item, you constantly render the ModalEditNgonNgu for every item. I believe that it is not the desired behavior you want to get. Assuming you want to show the item you clicked on, you can do something like:
function App() {
const [langs,setLangs] = useState([]);
const [selectedItem, setSelectedItem] = useState(undefined);
function handleUpdate(item){
console.log(item);
setSelectedItem(item);
}
return (<>
<table>
{langs.map((item, index) => {
<tr key={index}>
//Some code here
<td className='text-primary' style={{maxHeight: '21px',width: '8%',maxWidth: '300px'}} onClick={()=>handleUpdate(item)}>
This is item {item.id}
</td>
</tr>
}
</table>
{selected Item && <ModalEditNgonNgu item={selectedItem}/>}
</>);
}
In this code, we save the selected item in a state and create a single model based on the selected item.
Please note that this solution is not optimal. Most Modal implementation has some animations when they show up and disappear and should be shown by a property and not by the DOM. I guess you are using Bootstarp, so consider using some React wrapper like React-Boostrap and others.
Key property
When you render bunch of component in a loop, like map, you have to define a unique key prop to the child element, to let React follow and match different renders.
You added <tr key={index}> this is ok, but bad-practice. Key should be unique, index is NOT a good key value. The main goal of the key is let react track your componens. If you remove/insert items in the middle of the list, different items will have same key in different renders.
Since your item has an id property, you better do <tr key={item.id}>.
Arrow functions as props
Doing <td ... onClick={()=>handleUpdate(item)}> will work, but it creates a new function instance on every render, which will re-render every item in the list, every time that the list will be re-render.
It may be OK in your lightweight example, but it may cause performance issues in complex list, so you should avoid that.

Related

How to pass item's data to another component, edit data and save data in React.js?

I have a book table page to list all the books in the database, mapped with their book ID. If I click the book name, it will link to an edit book page, in this page, the input fields should be filled with the book detail, I can edit the book detail and save it in the database.
The problem is, how do I pass the book detail to another component?
Book table component
class BookTable extends Component {
constructor(props){
super(props)
this.state = {
books: [],
book: {}
}
render() {
return (
<div className='display-container'>
<div className="card-group-admin">
<div className="container">
<div className="row row-cols-3">
{this.state.books.map(book =>
<div className="card" style={{height:550 + 'px', width:320 + 'px'}} key={book._id}>
<img src={`http://localhost:3001/${book.bookImage}`} className="card-img-top" alt="comic book coverpage" />
<div className="card-body">
<Link to={`/books/${book._id}`} book={this.setState={book}}><h5 className="card-title">{book.bookName}</h5></Link>
<p className="card-text">{book.bookDescription}</p>
<div className="card-bottom-container">
<p className="card-status">{book.bookStatus}</p>
<button type="button" onClick={() => this.handleDeleteClick(book._id)}
className="btn btn-secondary" id="btnLength">Delete</button>
</div>
</div>
</div>)
}</div>
</div>
</div>
</div>
I am not sure whether "book={this.setState={book}}" inside the tag is correct or not, that's probably is where the problem at.
Edit component
import React, {useState} from 'react';
import { useHistory } from "react-router-dom";
import {book} from './BookTable';
function Edit ({book}) {
const [bookName, setBookName] = useState(book.bookName);
const [author, setAuthor] = useState(book.author);
const [publisher, setPublisher] = useState(book.publisher);
const [yearReleased, setYearReleased] = useState(book.yearReleased);
const [type, setType] = useState(book.type);
const [advancedBookType, setAdvancedBookType] = useState(book.advancedBookType);
const [rentalPrice, setRentalPrice] = useState(book.rentalPrice);
const [bookDescription, setBookDescription] = useState(book.bookDescription);
const handleSubmit = (e) => {
e.preventDefault();
const bookDetail = {
bookName,
author,
publisher,
yearReleased,
type,
advancedBookType,
rentalPrice,
bookDescription };
axios.put(`http://localhost:3001/app/books/${_id}`, bookDetail)
.then(response => {
console.log(response.data);
})
.catch(err => console.log(err));
}
const history = useHistory();
const handleBack = () => {
history.push("/adminDashboard");
}
return (
<div className="editPage">
<h1>Edit book page</h1>
<form onSubmit={handleSubmit} >
<label className="editLabel">Book name:</label>
<input type = 'text'
value={book.bookName}
onChange={(e) => setBookName(e.target.value)}
className="form-control form-group form-control-sm input" />
<label className="editLabel">Author:</label>
<input type = 'text'
value={book.author}
onChange={(e) => setAuthor(e.target.value)}
className="form-control form-group form-control-sm input" />
<label className="editLabel">Publisher:</label>
<input type = 'text'
value={book.publisher}
onChange={(e) => setPublisher(e.target.value)}
className="form-control form-group form-control-sm input" />
<label className="editLabel">Year released:</label>
<input type = 'number'
value={book.yearReleased}
onChange={(e) => setYearReleased(e.target.value)}
className="form-control form-group form-control-sm input" />
<label className="editLabel">Type:</label>
<select type = 'text'
value={book.type}
onChange={(e) => setType(e.target.value)}
className="form-control form-group form-control-sm input" id="exampleFormControlSelect1">
<option>Comedy</option>
<option>Love</option>
<option>Horror</option>
<option>Detecting</option>
<option>Fiction</option>
<option>Adventure</option>
<option>Action</option>
<option>Youth</option>
</select>
<label className="editLabel">Advanced book type:</label>
<select type = 'text'
value={book.advancedBookType}
onChange={(e) => setAdvancedBookType(e.target.value)}
className="form-control form-group form-control-sm input" id="exampleFormControlSelect1">
<option >None</option>
<option>Popular</option>
<option>New release</option>
</select>
<label className="editLabel">Rental price ($):</label>
<input type = 'number'
value={book.rentalPrice}
onChange={(e) => setRentalPrice(e.target.value)}
className="form-control form-group form-control-sm input" />
<label className="editLabel">Book description:</label>
<textarea value={book.bookDescription}
onChange={(e) => setBookDescription(e.target.value)}
className="form-control form-group textbox" rows="4">
</textarea>
<div className="buttonGroup">
<button onClick={() => handleBack()} className="btn btn-outline-dark">Back</button>
<input type="submit" className="btn btn-primary" id="right" value="Save" />
{/* <input type="reset" className="btn btn-outline-secondary" id="right" value="Delete" /> */}
</div>
</form>
</div>
);
}
export default Edit;
Backend book route
router.put('/books/:id', (request, response) => {
Book.findOneAndUpdate({ _id: request.params.id }, request.body, { new:true, useFindAndModify: false },
(err, book) => {
if (err) {
response.send(err);
}
response.json(book);
});
})
<Link to={{ pathname: `/books/${book._id}`, state: { data: book } }}> {book.bookName} </Link>
in Edit component
const { data } = props.location.state;

Unable to type in input field React

I am creating a simple todo list. In here there is a modal for the update form,I can take the relevant values from the state And set them to the input field values. then I can't edit the input fields. I think the problem is with the onChange function or value property
import React from 'react'
import {useRef,useState,useEffect} from 'react'
import {FaTimes} from 'react-icons/fa'
export const Modal = ({edData,showModal,setShowModal,onAdd,setEd,tasks}) => {
const [text,setText] = useState('')
const[day,setDay] = useState('')
const[reminder,setReminder] = useState(false)
useEffect(() => {
if(edData!=null){
for(let i=0;i<tasks.length;i++)
{
if(tasks[i].id===edData){
// console.log(tasks[i])
setText(tasks[i].text)
setDay(tasks[i].day)
setReminder(tasks[i].reminder)
}
}
}
// inputText.current.value = edData.text;
// inputDay.current.value = edData.day;
// inputReminder.current.value = edData.reminder;
});
const closeModal = () =>{
setEd(null)
setShowModal(prev=>!prev)
setText('')
setDay('')
setReminder(false)
}
const onSubmit = (e) =>{
e.preventDefault()
if (!text){
alert('Please add a task')
return
}
onAdd({text,day,reminder})
setText('')
setDay('')
setReminder(false)
setShowModal(prev=>!prev)
}
return (
<>
{showModal?
<div className="background">
<div className="ModalWrapper" >
<div className="ModalContent">
<h2 className="modalTitle">{edData==null? 'Add New Task':'Update Task'}</h2>
<form className="add-form" onSubmit={onSubmit}>
<div className="form-control">
<label htmlFor="">Task</label>
<input type="text" placeholder="Add Task" name="" id="" value={text} onChange={(e) => setText(e.target.value)}/>
</div>
<div className="form-control ">
<label htmlFor="">Date & Time</label>
<input type="text" placeholder="Add Date and Time" name="" id="" value={day} onChange={(e) => setDay(e.target.value)}/>
</div>
<div className="form-control form-control-check">
<label htmlFor="">Set Reminder</label>
<input type="checkbox" checked={reminder} name="" id="" value={reminder} onChange={(e) => setReminder(e.currentTarget.checked)}/>
</div>
<input className="btn btn-block" type="submit" value="Save Task" />
</form >
</div>
<div className="CloseModalButton" onClick={closeModal}>
<FaTimes/>
</div>
</div>
</div>
: null}
</>
)
}
If you don't pass a dependency array to useEffect it will be called on every render, calling setText inside of it and overwriting the input's value, pass an empty array to useEffect if you don't want it to run on every render :
useEffect(() => {
// ....
}, []);

Uncaught DOMException: This input element accepts a filename, which may only be programmatically set to the empty string

I already upload and get the list of product successful but Update product show for me an error. I do not know how to update my image and data on Firebase in Reactjs.
This is my code in ProductForm.js
import React, { useState, useEffect } from 'react';
import Gongcha from '../asses/gongcha.jpg'
const ProductForm = (props) => {
const initialFieldValues = {
image: '',
name: '',
category: '',
price: ''
};
var [values, setValues] = useState(initialFieldValues);
var [imageFile, setImageAsFile] = useState();
useEffect(() => {
if (props.currentId == '') setValues({ ...initialFieldValues });
else
setValues({
...props.productObjects[props.currentId],
});
}, [props.currentId, props.productObjects]);
const handleInputChange = (e) => {
var { name, value } = e.target;
setValues({
...values,
[name]: value,
});
};
const handleFormSubmit = (e) => {
e.preventDefault();
props.addOrEdit(values, imageFile);
};
const handleImageAsFile = (e) => {
console.log("file image",e);
const image = e.target.files[0]
setImageAsFile(imageFile => (image))
}
return (
<form autoComplete="off" onSubmit={handleFormSubmit}>
<div className="form-group input-group">
<div className="input-group-prepend">
<div className="input-group-text">
<i className="fas fa-image"></i>
</div>
</div>
<input
className="form-control"
type="file"
name="image"
placeholder="Image"
value={values.image}
onChange={handleImageAsFile}
/>
</div>
<div className="form-row">
<div className="form-group input-group col-md-6">
<div className="input-group-prepend">
<div className="input-group-text">
<i className="fas fa-mug-hot"></i>
</div>
</div>
<input
className="form-control"
name="name"
placeholder="Name"
value={values.name}
onChange={handleInputChange}
/>
</div>
<div className="form-group input-group col-md-6">
<div className="input-group-prepend">
<div className="input-group-text">
<i className="fas fa-list-alt"></i>
</div>
</div>
<input
className="form-control"
name="category"
placeholder="Category"
value={values.category}
onChange={handleInputChange}
/>
</div>
</div>
<div className="form-group input-group">
<div className="input-group-prepend">
<div className="input-group-text">
<i className="fas fa-money-check-alt"></i>
</div>
</div>
<input
className="form-control"
name="price"
placeholder="Price"
value={values.price}
onChange={handleInputChange}
/>
</div>
<div className="form-group">
<input
type="submit"
value={props.currentId == '' ? 'Save' : 'Update'}
className="btn btn-primary btn-block"
/>
</div>
</form>
);
};
export default ProductForm;
And this is the table, which the place I showed all list of product and also Action (Edit and Delete)
import React, { useState, useEffect } from 'react';
import { Card, Button, Imgage } from 'react-bootstrap'
import ProductForm from './ProductForm';
import { DB, Storage } from '../firebase';
const Products = () => {
var [currentId, setCurrentId] = useState('');
var [productObjects, setProductObjects] = useState({});
const [ImageAsUrl, setImageAsUrl] = useState()
useEffect(() => {
DB.ref().child('products').on('value', (snapshot) => {
if (snapshot.val() != null) {
setProductObjects({
...snapshot.val(),
});
}
});
}, []);
const addOrEdit = (obj, image_url) => {
let upload = Storage.ref().child(`product-img/${image_url.name}`).put(image_url)
upload.on('state_changed',
(snapShot) => {
console.log(snapShot)
}, (err) => {
console.log(err)
}, () => {
Storage.ref('product-img').child(image_url.name).getDownloadURL()
.then(fireBaseUrl => {
DB.ref().child('products').push({ name: obj.name, image: fireBaseUrl, category: obj.category, price: obj.price }, (err) => {
if (err) console.log(err);
else setCurrentId('');
})
})
})
console.log("log imgage link", ImageAsUrl);
};
const onDelete = (id) => {
if (window.confirm('Are you sure to delete this record?')) {
DB.ref().child(`products/${id}`).remove((err) => {
if (err) console.log(err);
else setCurrentId('');
});
}
};
return (
<>
<div className="jumbotron jumbotron-fluid">
<div className="container">
<h1 className="display-4 text-center">Products Manager</h1>
</div>
</div>
<div className="row">
<div className="col-md-5">
<ProductForm {...{ currentId, productObjects, addOrEdit }} />
</div>
<div className="col-md-7">
<table className="table table-borderless table-stripped">
<thead className="thead-light">
<tr>
<th>Image</th>
<th>Name</th>
<th>Category</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{Object.keys(productObjects).map((key) => (
<tr key={key}>
<td>{productObjects[key].image}</td>
<td>{productObjects[key].name}</td>
<td>{productObjects[key].category}</td>
<td>{productObjects[key].price}</td>
<td className="bg-light">
<a
type="button"
className="btn text-primary"
onClick={() => {
setCurrentId(key);
}}
>
<i className="fas fa-pencil-alt"></i>
</a>
<a
type="button"
className="btn text-danger"
onClick={() => {
onDelete(key);
}}
>
<i className="far fa-trash-alt"></i>
</a>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</>
);
};
export default Products;
This is an Error show for me when I clicked Update icon:
Uncaught DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.
Can anyone help me with this problem? I really do not know how to fix it. Please? Your help is my pleasure
As the error explains, you can not set a value property on an input / file element. Short example:
<input type="file" value="this throws an error" />
That means, you can not "pre-populate" the input field if the user already uploaded a file. You could show the file (if it's an image) and add a delete option (e.g button) next to it.

React state hooks and useEffect unexpected behavior for state updates

So I have a project I did before in Vue and now am doing in React(w/ hooks) in order to learn it. I'm having a few problems and concerns that I'm not going about it the right way(certain I'm not).
One of the biggest problems I'm having is where the state is updated via onchange and onblur. Many times the state values would be one "tick" behind. I found that with old class components you could use a callback within setState.
I'm trying to make instant form validation feedback show/hide as the user updates the fields.
With hooks, it is supposed to be done with useEffect. I have it "working" right now but it seems it's rendering more times than it should. I can tell by the fact it runs the checkValues() twice to show the current state values .
An example of the nature of my misunderstanding is if I don't put setinValid(validateForm()); within the onchange AND the useEffect.. it won't update the state for inValid which disables/enables the submit button. This seems redundant to me and I'm not sure why it "works" as is.
Any help/insight on how to properly do what I'm attempting would be greatly appreciated.
https://codesandbox.io/s/user-listing-in-react-9ip4t?fontsize=14&module=%2Fsrc%2Fcomponents%2FUser%2FUserAdd.js
import React from "react";
import { Link } from "react-router-dom";
// import { saveUserToLocalStorage } from "../../utils/StorageHelper";
// import { User } from "../../utils/UserClass";
const UserAdd = props => {
const [userName, setuserName] = React.useState("");
const [userAge, setuserAge] = React.useState("");
const [userEmail, setuserEmail] = React.useState("");
const [inValid, setinValid] = React.useState(true);
const [errors, setErrors] = React.useState({
name: [],
age: [],
email: []
});
React.useEffect(() => {
checkValues();
setinValid(validateForm());
}, [userName, userAge, userEmail, inValid]);
const validateForm = () => {
if (isNaN(userAge)) {
return true;
}
if (!userName || !userAge || !userEmail) {
return true;
}
if (!validateEmail(userEmail)) {
return true;
}
return false;
};
function checkIndividualErrors() {
if (userName.length === 0) {
setErrors({ ...errors, name: ["User name is required"] });
} else {
setErrors({ ...errors, name: [] });
}
}
const checkValues = () => {
console.log(
"username:",
userName,
"age:",
userAge,
"useremail: ",
userEmail,
"invalid:",
inValid
);
};
const validateEmail = mail => {
if (/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(mail)) {
return true;
}
return false;
};
return (
<div>
<h2 class="line-container">
<span>Add a new User</span>
</h2>
<hr />
<div class="field is-horizontal">
<div class="field-label is-normal">
<label class="label">Name</label>
</div>
<div class="field-body">
<div class="field">
<p class="control">
<input
class="input"
type="text"
name="name"
placeholder="Name"
value={userName}
onChange={e => {
setuserName(e.target.value);
setinValid(validateForm());
checkIndividualErrors();
}}
onBlur={checkIndividualErrors}
/>
<span class="error">{errors.name}</span>
</p>
</div>
</div>
</div>
<div class="field is-horizontal">
<div class="field-label is-normal">
<label class="label">Age</label>
</div>
<div class="field-body">
<div class="field">
<p class="control">
<input
class="input"
type="text"
name="age"
placeholder="Age"
value={userAge}
onChange={e => {
setuserAge(e.target.value);
setinValid(validateForm());
// checkIndividualErrors not fully implemented yet
}}
/>
<span class="error" />
</p>
</div>
</div>
</div>
<div class="field is-horizontal">
<div class="field-label is-normal">
<label class="label">Email</label>
</div>
<div class="field-body">
<div class="field">
<p class="control">
<input
class="input"
type="email"
name="email"
placeholder="Email"
value={userEmail}
onChange={e => {
setuserEmail(e.target.value);
setinValid(validateForm());
// checkIndividualErrors not fully implemented yet
}}
/>
<span class="error" />
</p>
</div>
</div>
</div>
<p class="" style={{ margin: "0 auto" }}>
<button
disabled={inValid}
class="button is-primary"
style={{ marginRight: "10px" }}
>
Create
</button>
<Link to="/" class="button">
Cancel
</Link>
<Link to="/" class="goBack">
<span style={{ fontSize: "20px" }}>←</span>
</Link>
</p>
</div>
);
};
export default UserAdd;

How to get the value from button group in react component

Below is the button group component which I used inside the form.How to implement the onchange functions to this button group.I have no Idea how to set the onchange method
import React, {Component} from "react";
import {Popover, OverlayTrigger} from 'react-bootstrap';
import "./ButtonGroup.scss";
const popoverBottom = () =>{
return (
<Popover className="tooltip-popover" title="Here is the where you
give a tooltip">
</Popover>
);
}
export const ButtonGroup = ({
tooltip,
label,
options,
selected,
lableStyle = {},
Title = "Tooltip on top",
}) => {
return (
<div className="nuclei-group">
<p className="nuclei-buttongroup-input"> {label} </p>
<div data-toggle="buttons">
{options.map((option, i) => {
const className = selected == option.value ? "active" : "";
return (
<label
key={i}
style={lableStyle}
className={`btn btn-default nuclei-selection-option ${className}`}
>
<input
type="radio"
name={"name"}
id={option.value}
autoComplete="off"
/>
{option.label}
</label>
);
})}
{tooltip ? (
<span>
<OverlayTrigger trigger="click" rootClose placement="bottom" overlay={popoverBottom()}>
<button type="button" className="btn nuclei-tooltip">?</button>
</OverlayTrigger>
</span>
) : null}
</div>
</div>
);
};
export default ButtonGroup;
then I tried to add on change as below and after submitting the form it doesn't work can somebody help me to resolve it.Normally inside a input tag it works but here? and let me know is this the best way to get values from a form as in the code below
import React, {Component} from "react";
import "./classic-quote.scss";
import {Button, ButtonGroup, InputText} from "../../../components";
import StepBreadcrumb from "../../../components/StepBreadcrumb";
import HeaderTitle from "../../../components/HeaderTitle";
import axios from 'axios';
export default class ClassicQuote extends Component {
constructor(props){
super(props);
this.state = {
insurance_type:'',
vehicle_registration:'',
lease_loan_hire:'',
estimated_market_value:'',
usage:'',
make:'',
model:'',
year:'',
claim_bonus_year:''
}
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange1 = this.handleChange1.bind(this);
this.handleChange2 = this.handleChange2.bind(this);
this.handleChange3 = this.handleChange3.bind(this);
this.handleChange4 = this.handleChange4.bind(this);
}
handleChange1(e){
this.setState({
make: e.target.value
})
}
handleChange2(e){
this.setState({
model: e.target.value
})
}
handleChange3(e){
this.setState({
year: e.target.value
})
}
handleChange4(e){
this.setState({
insurance_type: e.target.id
})
}
handleSubmit(e){
e.preventDefault();
const quotation = {
make: this.state.make,
model: this.state.model,
year: this.state.year,
insurance_type: this.state.insurance_type
}
console.log('gggggggg'+quotation.make+quotation.model+quotation.year+quotation.insurance_type);
let uri = '/items'
axios.post(uri,quotation).then(response => {
console.log('ela');
}).then(error => {
console.log(error);
});
}
render() {
return <div>
{/* <StepBreadcrumb id="bred" /> */}
<div className="container insureme-form zero-padding">
<form onSubmit={this.handleSubmit}>
<div className="row">
<HeaderTitle mainFirstWord="Insurance" restOfTitle="Detail" headerStyle={{fontWeight: "bold"}} headerIcon={true} />
<div className="nuclei-insurance-detail-step-one">
<div className="col-md-12 col-sm-12 col-xs-12">
<ButtonGroup onChange={this.handleChange4} label="" selected="full" options={[{label: "Full Insurance", value: "full"}, {label: "3rd Party Insurance", value: "3rd"}]} tooltip />
<pre>{JSON.stringify(this.state, '', 2)}</pre>
</div>
<div className="col-md-12 col-sm-12 col-xs-12">
<ButtonGroup label="Do you have a vehicle registration No?" selected="Yes" options={[{label: "Yes", value: "Yes"}, {label: "No", value: "No"}]} tooltip />
</div>
<div className="col-md-12 col-sm-12 col-xs-12">
<ButtonGroup label="Do you have any lease,Loan or hire on vehicle?" selected="Yes" options={[{label: "Yes", value: "Yes"}, {label: "No", value: "No"}]} tooltip />
</div>
<div className="col-md-4 col-sm-4 col-xs-8">
<InputText label={"Estimated Market Value?"} placeholder="Rs." />
</div>
<div className="col-md-12 col-sm-12 col-xs-12">
<ButtonGroup label="Usage?" selected="Private" options={[{label: "Private", value: "Private"}, {label: "Hire", value: "Hire"}, {label: "Rent", value: "Rent"}]} tooltip />
</div>
<div className="col-md-12 col-sm-12 col-xs-12 form-group input-text ">
<label>Make, Model and Year of Manufacture? </label>
<div className="col-md-4 col-sm-4 col-xs-4 zero-padding-left">
<input type="text" className="form-control" id={"make-manufacture"} placeholder={"Make"} onChange={this.handleChange1} />
</div>
<div className="col-md-3 col-sm-3 col-xs-4 zero-padding-left">
<input type="text" className="form-control" id={"model-manufacture"} placeholder={"Model"} onChange={this.handleChange2}/>
</div>
<div className="col-md-2 col-sm-2 col-xs-3 zero-padding-left">
<input type="text" className="form-control" id={"year-manufacture"} placeholder={"Year"} onChange={this.handleChange3}/>
</div>
</div>
<div className="col-md-12 col-sm-12 col-xs-12 form-group input-text">
<label>No Claims Bonus?</label>
<div className="col-md-4 col-sm-4 col-xs-8 zero-padding-left">
<InputText tooltip placeholder="No. of Years" />
</div>
</div>
<div className="col-md-12 col-sm-12 col-xs-12">
<Button type="submit" color="red" className="nuclei-bottom-red-button">
Get a Quick Quote
</Button>
<Button type="clear" color="gray" className="nuclei-bottom-gray-button">
Clear
</Button>
</div>
</div>
</div>
</form>
</div>
</div>;
}
}
I tried several ways can get only the make model and year values as printed in the console log
if you want to pass an handler like this:
onChange={this.handleChange4}
you have to add it to the props you receive in Component:
export const ButtonGroup = ({
onChange,
tooltip,
label,
options,
selected,
lableStyle = {},
Title = "Tooltip on top",
}) => {
...
and then in the input elements call onChange:
<input
onChange={onChange}
type="radio"
name={"name"}
id={option.value}
autoComplete="off"
/>
If you want to see the complete solution, I build it in sandbox: Full example here
I saw that you update the form, but you didn't add "onChange" in the ButtonGroup Component file like in the comment:
export const ButtonGroup = ({
onChange, <---this
tooltip,
label,
options,
selected,
lableStyle = {},
Title = "Tooltip on top",
}) => {
return (
<div className="nuclei-group">
<p className="nuclei-buttongroup-input"> {label} </p>
<div data-toggle="buttons">
{options.map((option, i) => {
const className = selected == option.value ? "active" : "";
return (
<label
key={i}
style={lableStyle}
className={`btn btn-default nuclei-selection-option ${className}`}
>
<input
onChange={onChange} <---this
type="radio"
name={"name"}
id={option.value}
autoComplete="off"
/>
{option.label}
</label>
);
})}

Resources