trigger functions with radio buttons React/TS - reactjs

I have radio buttons that look like this:
<div className="row">
<div className="col-md-4">
<label className="radio">
<input onChange={() => {serviceCalc()}} type="radio" name="radio-btn-product" value="standard" id="standard" checked />
<i></i>Standard
</label>
</div>
<div className="col-md-4">
<label className="radio">
<input onChange={() => {serviceCalc()}} type="radio" name="radio-btn-product" value="premium" id="premium" />
<i></i>Premium
</label>
</div>
<div className="col-md-4">
<label className="radio">
<input onChange={() => {serviceCalc()}} type="radio" name="radio-btn-product" value="excelium" id="excelium" />
<i></i>Excelium
</label>
</div>
</div>
I'm trying to get the serviceCalc function to trigger the three other functions depending on which radio button is clicked like so:
const serviceCalc = () => {
const standard1 = (document.getElementById("standard") as HTMLInputElement);
const premium1 = (document.getElementById("premium") as HTMLInputElement);
const excelium1 = (document.getElementById("excelium") as HTMLInputElement);
if (standard1.checked){
standard();
}
else if (premium1.checked) {
premium();
}
else if (excelium1.checked) {
excelium();
}
}
but when I select the standard option for example, this wont trigger:
const standard = () => {
console.log('stand_test')
}
any help is greatly appreciated.

The isssue is that your radio buttons are controlled (you have an onChange on them and you have checked on one of them), but you're only ever setting checked on standard. Since standard is always checked, clicking standard isn't changing anything, so the change event isn't raised.
Separately, onChange={() => {serviceCalc()}} should almost always be onChange={serviceCalc}.
Normally, when you're using controlled inputs, you store the state in the component state. Here's an example:
const { useState } = React;
const Example = () => {
const [serviceLevel, setServiceLevel] = useState("standard");
const serviceCalc = ({currentTarget: {value}}/*: {currentTarget: HTMLInputElement}*/) => {
setServiceLevel(value);
// If you need to run other functions here, you can do that
// with an `if`/`else`/etc. on `value`, which is
// `"standard"`, `"premium"`, or `"excelium"
};
// This is purely to show the new service level
console.log(`service level is ${serviceLevel}`);
return (
<div className="row">
<div className="col-md-4">
<label className="radio">
<input onChange={serviceCalc} type="radio" name="radio-btn-product" value="standard" checked={serviceLevel === "standard"} />
<i></i>Standard
</label>
</div>
<div className="col-md-4">
<label className="radio">
<input onChange={serviceCalc} type="radio" name="radio-btn-product" value="premium" checked={serviceLevel === "premium"} />
<i></i>Premium
</label>
</div>
<div className="col-md-4">
<label className="radio">
<input onChange={serviceCalc} type="radio" name="radio-btn-product" value="excelium" checked={serviceLevel === "excelium"} />
<i></i>Excelium
</label>
</div>
</div>
);
};
ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

Pass a parameter depending on which button was checked:
const serviceCalc = (service: "standard" | "premium" | "excelium") => {
if (service === "standard") {
return standard();
}
if (service === "premium") {
return premium();
}
if (service === "excelium") {
return excelium();
}
}
And you would use it like so:
<div className="col-md-4">
<label className="radio">
<input onChange={() => {serviceCalc("excelium")}} type="radio" name="radio-btn-product" value="excelium" id="excelium" />
<i></i>Excelium
</label>
</div>

Related

radio input still true after unchecked

I have filter section with checkbox and radio when user unchecked for checkbox the content is hidding, but for radio I can't hidden the content he still true.
Any help please
const inputChecked = (e) => {
const updatedList = [...checked];
if (e.target.checked) {
updatedList = [...checked, e.target.value];
}
else {
updatedList.splice(checked.indexOf(e.target.value),1)
}
setChecked(updatedList);
};
return (
<form>
<div onChange={inputChecked}>
<div className='flex items-center'>
<input type='radio' id="most_recent" name="sort_by" value='Most recent' />
<label htmlFor='most_recent'>Most recent</label>
</div>
<div className='flex items-center'>
<input type='radio' id="most_relevent" name="sort_by" value='Most relevent' />
<label htmlFor='most_relevent'>Most relevent</label>
</div>
</div>
<div onChange={inputChecked}>
<div className='flex items-center'>
<input type='checkbox' id="intership" name="intership" value='intership' />
<label htmlFor='intership'>intership</label>
</div>
<div className='flex items-center'>
<input type='checkbox' id="Director" name="director" value='Director' />
<label htmlFor='Director'>Director</label>
</div>
<div className='flex items-center'>
<input type='checkbox' id="Associate" name="associate" value='Associate' />
<label htmlFor='Associate'>Associate</label>
</div>
</div>
</form>
)
Separate into two types of handle: handle for radio checked and handle for checkbox checked.
Have to put onChange into each radio input <input type="radio" onChange={}... />. Try this below code:
const [prevRadio, setPrevRadio] = useState("")
const radioChecked = (e) => {
setPrevRadio(e.target.value)
let updatedList = [...checked, e.target.value];
updatedList.splice((prevRadio ? checked.indexOf(prevRadio) : (checked.length + 99)),1)
setChecked(updatedList)
}
const inputChecked = (e) => {
let updatedList = [...checked];
if (e.target.checked) {
updatedList = [...checked, e.target.value];
}
else {
updatedList.splice(checked.indexOf(e.target.value),1)
}
setChecked(updatedList);
};
return (
<form>
<div>
<div className='flex items-center'>
<input type='radio' id="most_recent" name="sort_by" value='Most recent'
onChange={inputChecked}/> //<== Put onChange in here
<label htmlFor='most_recent'>Most recent</label>
</div>
<div className='flex items-center'>
<input type='radio' id="most_relevent" name="sort_by" value='Most relevent'
onChange={inputChecked}/> //<== Put onChange in here
<label htmlFor='most_relevent'>Most relevent</label>
</div>
</div>
<div onChange={inputChecked}>
<div className='flex items-center'>
<input type='checkbox' id="intership" name="intership" value='intership' />
<label htmlFor='intership'>intership</label>
</div>
<div className='flex items-center'>
<input type='checkbox' id="Director" name="director" value='Director' />
<label htmlFor='Director'>Director</label>
</div>
<div className='flex items-center'>
<input type='checkbox' id="Associate" name="associate" value='Associate' />
<label htmlFor='Associate'>Associate</label>
</div>
</div>
</form>
)

How to create a RadioButtonGroup with "pure" react?

I am trying to create a radio group that can be handled with the onChange function provided to the parent div:
const handleAgeGroupOnChange = (e) => {
console.log(e.target.value)
};
<div onChange={handleAgeGroupOnChange} className="flex flex-col">
<label>
<input type="radio" value="18-34" name="18-34" />
18-34
</label>
<label>
<input type="radio" value="35-49" name="35-49" />
35-49
</label>
<label>
<input type="radio" value="50+" name="50+" />
50+
</label>
<label>
<input type="radio" value="all" name="Mix all ages" />
Mix all ages
</label>
</div>
The logging is working, I am getting all of the correct values, however the checked state of the buttons is not updated correctly, if I click all of the buttons, all of them will stay checked.
Do I have to do the checked property for each button, and is there a way to do this, without having to manually do checked on each radio button?
To make things easier, I would put the options into an array and just map them like the below and give each radio button the same name and just make them readOnly.
const options = ["18-34", "35-49", "50+", "Mix all ages"];
function App() {
const [age, setAge] = React.useState("");
const handleOnChange = (evt) => {
const { value } = evt.target;
setAge(value);
};
return (
<div className="App">
{options.map((option) => (
<div key={option}>
<label>
<input
type="radio"
name="age"
value={option}
readOnly={true}
checked={age === option}
onChange={handleOnChange}
/>
{option}
</label>
</div>
))}
<pre>Selected option: {age}</pre>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

How to add multiple checkboxes to a state

How to save multiple checkboxes to a single state and add each checkbox to its previous state?
These are my states:
Operators : '',
TypeStatus : '',
RegistrationStatus : '',
This is my function:
changeHandle = (event) => {
this.setState({
[event.target.name]: event.target.value
});
};
This is my input:
I want to click on each of these checkboxes to add the value to the state
and add the RegisterButtonsActivated class to its parent label
<div className="container-fluid">
<div className="row flex-row-reverse">
<div className="col" data-toggle="buttons">
<label className="RegisterButtons">
<input
type="checkbox"
name="Operators"
id="MCI"
value="MCI"
checked={this.state.operations}
onChange={this.changeHandle}
onClick={this.props.handleFilterOperatorMCI}
/>
همراه اول
</label>
</div>
<div className="col" data-toggle="buttons">
<label className="RegisterButtons">
<input
type="checkbox"
name="Operators"
id="irancell"
value="irancell"
checked={true}
onChange={this.changeHandle}
onClick={this.props.handleFilterOperatorIrancell}
/>
ایرانسل
</label>
</div>
<div className="col" data-toggle="buttons">
<label className="RegisterButtons">
<input
type="checkbox"
name="Operators"
id="rightel"
value="rightel"
checked={this.state.operations}
onChange={this.changeHandle}
onClick={this.handleFilterOperatorRightel}
/>
رایتل
</label>
</div>
</div>
<div className="row justify-content-center">
<div className="col">
<hr className="hr-Filterbox" />
</div>
</div>
<div className="row flex-row-reverse">
<div className="col">
<label className={`RegisterButtons ${this.state.TypeStatus ===
"Justice" ? 'RegisterButtonsActivated' : ''}`}>
<input
type="checkbox"
name="TypeStatus"
id="Justice"
value="Justice"
onChange={this.changeHandle}
onClick={this.props.handleFilterTypeJustice}
/>
دائمی
</label>
</div>
<div className="col">
<label className={`RegisterButtons ${this.state.TypeStatus ===
"Credit" ? 'RegisterButtonsActivated' : ''}`}>
<input
type="checkbox"
name="TypeStatus"
id="Credit"
value="Credit"
onChange={this.changeHandle}
onClick={this.props.handleFilterTypeCredit}
/>
اعتباری
</label>
</div>
</div>
<div className="row justify-content-center">
<div className="col">
<hr className="hr-Filterbox" />
</div>
</div>
<div className="row flex-row-reverse">
<div className="col" data-toggle="buttons">
<label className={`RegisterButtons ${this.state.OperatingStatus
=== "New" ? 'RegisterButtonsActivated' : ''}`}>
<input
type="checkbox"
name="OperatingStatus"
id="New"
value="New"
onChange={this.changeHandle}
onClick={this.props.handleFilterWorkStatusNew}
/>
صفر
</label>
</div>
<div className="col" data-toggle="buttons">
<label className={`RegisterButtons ${this.state.OperatingStatus
=== "LowPerformance" ? 'RegisterButtonsActivated' : ''}`}>
<input
type="checkbox"
name="OperatingStatus"
id="LowPerformance"
value="LowPerformance"
onChange={this.changeHandle}
onClick={this.props.handleFilterWorkStatusOld}
/>
کم کارکرد
</label>
</div>
<div className="col" data-toggle="buttons">
<label className={`RegisterButtons ${this.state.OperatingStatus
=== "Old" ? 'RegisterButtonsActivated' : ''}`}>
<input
type="checkbox"
name="OperatingStatus"
id="Old"
value="Old"
onChange={this.changeHandle}
onClick={this.props.handleFilterWorkStatusLowPerformance}
/>
کارکرده
</label>
</div>
</div>
</div>
I want to click on each of these checkboxes to add the value to the state and add the RegisterButtonsActivated class to its parent label
You can do like this.....
this.state = {
checkboxes: {
Operators: null,
TypeStatus: null,
RegistrationStatus: null,
}
}
Below will handle the change in existing state and if you will pass new checkbox it will add new key to the state object.
changeHandle = (event) => {
this.setState((prevState) => ({
checkboxes: {...prevState.checkboxes, [event.target.name]: event.target.value }
}))
};
You can do this with your state;
this.state = {
checkboxes: {
Operators: {
currentValue: null,
previousValues:[]
},
TypeStatus: {
currentValue: null,
previousValues:[]
},
RegistrationStatus: {
currentValue: null,
previousValues:[]
},
}
}
Now your handler will look something like this;
changeHandle = (event) => {
const checkboxes = this.state.checkboxes;
checkboxes[event.target.name].currentValue = event.target.value;
checkboxes[event.target.name].previousValues.push(event.target.value); // last element will be the latest value.
this.setState({
checkboxes
});
};

Showing input value in the url link (ReactJs Laravel)

I created laravel project with the reactjs framework and I'm new for this framework. I have problem and why It happens every time i submit the form.
Goal: users can register through online
Problem:
Why it happens when i submit the button the input value of user shown in the url link?
The data that I input is not inserted to the database.
Code:
constructor() {
super();
this.state = {
f_name:'',
l_name:'',
m_name:'',
email:'',
home_num:'',
contact_num:'',
Job_name:[],
employ_status:'',
employ_relocate:'',
employ_start_date:'',
employ_file:''
}
this.handleSubmit = this.handleSubmit.bind(this);
this.handle_fname = this.handle_fname.bind(this);
this.handle_lname = this.handle_lname.bind(this);
this.handle_mname = this.handle_mname.bind(this);
this.handle_email = this.handle_email.bind(this);
this.handle_homenum = this.handle_homenum.bind(this);
this.handle_contactnum = this.handle_contactnum.bind(this);
this.handle_employ_status = this.handle_employ_status.bind(this);
this.handle_employ_relocate = this.handle_employ_relocate.bind(this);
this.handle_employ_start_date = this.handle_employ_start_date.bind(this);
this.handle_employ_file = this.handle_employ_file.bind(this);
}
componentDidMount() {
const id = this.props.match.params.id;
axios.get('/api/online_application_job_title/' +id).then(response => {
this.setState({
Job_name:response.data
})
})
}
handleSubmit(e)
{
const data = {
firstname: this.state.f_name,
lastname : this.state.l_name,
middlename : this.state.m_name,
email : this.state.email,
home_number : this.state.home_num,
contact_num : this.state.contact_num,
job : this.state.Job_name[0].position_name,
employ_status : this.state.employ_status,
employ_relocate : this.state.employ_relocate,
employ_start_date : this.state.employ_start_date,
employ_file : this.state.employ_file
}
axios.post('/api/save_application',data).then(response => {
console.log(response);
}).catch(error => console.log(error));
}
handle_fname(e)
{
this.setState({
f_name:e.target.value,
})
}
handle_lname(e){
this.setState({
l_name:e.target.value,
})
}
handle_mname(e){
this.setState({
m_name:e.target.value,
})
}
handle_email(e){
this.setState({
email:e.target.value,
})
}
handle_homenum(e){
this.setState({
home_num:e.target.value
})
}
handle_contactnum(e){
this.setState({
contact_num:e.target.value
})
}
handle_employ_status(e){
this.setState({
employ_status:e.target.value
});
}
handle_employ_relocate(e){
this.setState({
employ_relocate:e.target.value,
})
}
handle_employ_start_date(e){
this.setState({
employ_start_date:e.target.value,
})
}
handle_employ_file(e){
this.setState({
employ_file: e.target.files[0].extension
})
}
renderName() {
return (
this.state.Job_name.map(name => (
<input placeholder="" value={name.position_name} type="text" className="form-control"/>
))
)
}
render() {
return (
<div>
<div className="header">
<div className="jumbotron">
<h1>Online Application</h1>
</div>
</div>
<form onSubmit={this.handleSubmit}>
<div className="container">
<h5><b>Personal Info</b></h5>
<br/>
<div className="row">
<div className="col-md-6">
<input
placeholder="First Name*"
value={this.state.f_name}
onChange={this.handle_fname}
className="form-control"/>
</div>
<div className="col-md-6">
<input
placeholder="Last Name*"
value={this.state.l_name}
onChange={this.handle_lname}
className="form-control"/>
</div>
</div>
<br/>
<div className="row">
<div className="col-md-6">
<input
placeholder="Middle Name*"
value={this.state.m_name}
onChange={this.handle_mname}
className="form-control"/>
</div>
<div className="col-md-6">
<input
placeholder="Email Address*"
type="email"
value={this.state.email}
onChange={this.handle_email}
className="form-control"/>
</div>
</div>
<br/>
<div className="row">
<div className="col-md-6">
<input
placeholder="Home Number*"
type="number"
value={this.state.home_num}
onChange={this.handle_homenum}
className="form-control"/>
</div>
<div className="col-md-6">
<input
placeholder="Contact Number*"
type="number"
value={this.state.contact_num}
onChange={this.handle_contactnum}
className="form-control"/>
</div>
</div>
<br/><br/>
<h5><b>Employment Application</b></h5>
<br/>
<div className="row">
<div className="col-md-6">
<p>Position Applying For</p>
{this.renderName()}
</div>
<div className="col-md-6">
</div>
</div>
<br/><br/>
<div className="row">
<div className="col-md-6">
<p>1. What is your current employment status?</p>
<div className="form-check-inline">
<label className="form-check-label">
<input
type="radio"
className="form-check-input"
name="employmentstatus"
onChange={this.handle_employ_status}
defaultChecked={false}
value="Unemployed"/>Unemployed
</label>
</div>
<div className="form-check-inline">
<label className="form-check-label">
<input
type="radio"
className="form-check-input"
name="employmentstatus"
onChange={this.handle_employ_status}
defaultChecked={false}
value="Employed"/>Employed
</label>
</div>
<div className="form-check-inline disabled">
<label className="form-check-label">
<input
type="radio"
className="form-check-input"
name="employmentstatus"
onChange={this.handle_employ_status}
defaultChecked={false}
value="Self-Employed"/>Self-Employed
</label>
</div>
<div className="form-check-inline disabled">
<label className="form-check-label">
<input
type="radio"
className="form-check-input"
name="employmentstatus"
onChange={this.handle_employ_status}
defaultChecked={false}
value="Student"/>Student
</label>
</div>
</div>
<div className="col-md-6"></div>
</div>
<br/>
<div className="row">
<div className="col-md-6">
<p>2. Are you willing to relocate?</p>
<div className="form-check-inline">
<label className="form-check-label">
<input type="radio"
name="relocate"
onChange={this.handle_employ_relocate}
className="form-check-input"
value="Yes"/>Yes
</label>
</div>
<div className="form-check-inline">
<label className="form-check-label">
<input type="radio"
name="relocate"
onChange={this.handle_employ_relocate}
className="form-check-input"
value="No"/>No
</label>
</div>
</div>
<div className="col-md-6"></div>
</div>
<br/>
<div className="row">
<div className="col-md-6">
<p>3. When is your available start date?</p>
<input
name="startdate"
type="date"
onChange={this.handle_employ_start_date}
value={this.state.employ_start_date}
required=""
className="form-control"/>
</div>
<div className="col-md-6"></div>
</div>
<br/>
<div className="row">
<div className="col-md-6">
<p>4. Kindly attach a copy of your resume (PDF,docx files only).</p>
<div className="custom-file">
<input
type="file"
name="file"
accept="application/msword,application/pdf"
onChange={this.handle_employ_file}
className="custom-file-input"
id="inputGroupFile04"/>
<label className="custom-file-label" htmlFor="inputGroupFile04">Choose file</label>
</div>
</div>
<div className="col-md-6"></div>
</div>
<br/>
<div className="row">
<div className="col-md-6">
<input
className="btn btn-outline-primary btn-large form-control col-md-5"
type="submit"
value="Send Application"/>
</div>
<div className="col-md-6"></div>
</div>
</div>
</form>
</div>
)
}
Controller:
public function save_application(Request $request)
{
$firstname = $request->get('firstname');
$lastname = $request->get('lastname');
$middlename = $request->get('middlename');
$email = $request->get('email');
$home_number = $request->get('home_number');
$contact_num = $request->get('contact_num');
$job = $request->get('job');
$employ_status = $request->get('employ_status');
$employ_relocate = $request->get('employ_relocate');
$employ_start_date = $request->get('employ_start_date');
$employ_file = $request->get('employ_file');
$now = new DateTime();
DB::insert('INSERT INTO onlineapplication
(position_name,firstname,middlename,lastname,email,homenumber,phonenumber,employmentstatus,relocate,starting_date,destination,file_img_name,Status)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)',[
$firstname,
$lastname,
$middlename,
$email,
$home_number,
$contact_num,
$job,
$employ_status,
$employ_relocate,
$employ_start_date,
$employ_file
]);
return response()->json('Successfully inserted');
}
When form tag is used, the submit will trigger the default behaviour that is based on the method provided and the action url.
as in your example you are handling the data explicitly you should prevent the default behaviour.
add the below code in handle submit
handleSubmit(e) {
e.preventDefault();
...
...
}
this will prevent the default behaviour.
Improvement for state update:
you don't need individual functions to update the input value to state this can be combined in one function.
to combine, provide the input name same as state name.
this.state ={
"f_name": '',
"l_name": '',
...
}
<input name="f_name" ... onChange={this.handleInputChange}/>
<input name="l_name" .. onChange={this.handleInputChange}/>
handleInputChange(e){
let target = e.target;
let name = target.name;
let value = target.value
this.setState({[name]: value})
}
for more info refer this link.
First, I just want to introduce to you to the arrow function in JavaScript (ES6). Declaring private methods like this:
handle_fname = (e) =>
{
this.setState({
f_name:e.target.value,
})
}
will save you time from unnecessary binding in the constructor.
Regarding your question, you missed to show the content of your this.handleSubmit(). Without this, I can assume that the form submit fired a get call since you failed to put method attribute in your <form/> tag, and without indicating your method attribute will result to default get method. Get method when used, data submitted will be visible in the page address field of your browser.
EDIT
You already added your handleSubmit() in your question, and it looks okay. If data is still shown in the address field of your browser, try adding method="post" in your form tag like this:
<form onSubmit={this.handleSubmit} method="post">

React render function within a function in JSX?

In my component's render function I'm calling anouther function with markup. So far so good.
renderEquipmentOptions() {
return (
<div className="form-check">
<label className="form-check-label">
<input className="form-check-input" type="checkbox" value=""/>
Nothing
</label>
</div>
)
}
However now I want to add a map to this function to generate additional markup.
renderEquipmentOptions() {
const render = this.props.equipment.map((item, i) => {
return (
<div key={i} className="form-check form-check-inline">
<label className="form-check-label">
<input className="form-check-input" type="checkbox" value=""/>
{item}
</label>
</div>
)
});
return (
<div className="form-check">
<label className="form-check-label">
<input className="form-check-input" type="checkbox" value=""/>
Nothing
</label>
</div>
{this.render()}
)
}
This doesn't work. It seems you cant wrap a function in {} and call it. Is this because its a function within a function?
It doesn't work because you are trying to return multiple elements from the function without returning them as an array. Also render is not a function in your case but a variable
change your code to return an array like
renderEquipmentOptions() {
const render = this.props.equipment.map((item, i) => {
return (
<div key={i} className="form-check form-check-inline">
<label className="form-check-label">
<input className="form-check-input" type="checkbox" value=""/>
{item}
</label>
</div>
)
});
return (
[<div className="form-check">
<label className="form-check-label">
<input className="form-check-input" type="checkbox" value=""/>
Nothing
</label>
</div>,
...render
]
)
}

Resources