Reputation: 629
Currently getting to grips with JS and React. I want to map the value from the selected option to this.state.transcode_profile
. I have tried the same method as I am using on the input
tags unfortunately this is not working.
Here's the code, what am I doing wrong?
import React, { Component } from "react";
const ProfileList = ({profiles}) => (
<select name="transcode_profile"
id="transcode_profile"
onChange={this.onChange}>
<option value="-----">----</option>
{profiles.map(profile => <option value={profile.name}>{profile.name}</option>)}
</select>
);
const url = 'http://localhost:8000/api/tasks/';
class Submit_job extends Component {
constructor(){
super();
this.state = {
"profiles": [],
"material_id": null,
"transcode_profile": null,
"start_date": null,
"end_date": null,
};
};
componentDidMount(){
fetch("http://localhost:8000/api/profiles/")
.then(response => response.json())
.then(response => this.setState({ profiles: response}))
}
onChange = (e) => {
// Because we named the inputs to match their corresponding values in state, it's
// super easy to update the state
const state = this.state;
state[e.target.name] = e.target.value;
this.setState(state);
};
handleChange(e){
this.setState({selectValue:e.target.value});
};
postData = (e) => {
e.preventDefault();
// Default options are marked with *
return fetch(url, {
body: JSON.stringify({status: 'submitted',
video_data: {material_id: this.state.material_id},
profile_data: {name: this.state.transcode_profile },
start: this.state.start_date,
end: this.state.end_date,
user: 'Foobar'}), // must match 'Content-Type' header
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, same-origin, *omit
headers: {
'user-agent': 'Mozilla/4.0 MDN Example',
'content-type': 'application/json'
},
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, cors, *same-origin
redirect: 'follow', // *manual, follow, error
referrer: 'no-referrer', // *client, no-referrer
})
.then(response => response.json()) // parses response to JSON
};
render() {
return (
<div>
<h2>Submit Job</h2>
<form onSubmit={this.postData}>
<label htmlFor="material_d">Material ID:</label>
<input id="material_id"
type="text"
name="material_id"
onChange={this.onChange}
required/>
<br/>
<label htmlFor={"transcode_profile"}>Transcode Profile:</label>
<ProfileList profiles={this.state.profiles}/>
<br/>
<label htmlFor="start_date">Start Date:</label>
<input type="text"
name="start_date"
id="start_date"
onChange={this.onChange}
required/>
<br/>
<label htmlFor="end_data">End Date:</label>
<input type="text"
name="end_date"
id="end_date"
onChange={this.onChange}
required/>
<br/>
<button>Submit</button>
</form>
</div>
);
}
}
export default Submit_job;
Edit: This is how i got it working.
import React, { Component } from "react";
const ProfileList = ({onChange, profiles, value}) => (
<select name="transcode_profile"
id="transcode_profile"
onChange={onChange}
value={value}>
<option value="-----">----</option>
{profiles.map(profile => <option value={profile.name}>{profile.name}</option>)}
</select>
);
const url = 'http://localhost:8000/api/tasks/';
class Submit_job extends Component {
constructor(){
super();
this.state = {
"profiles": [],
"material_id": null,
"transcode_profile": null,
"start_date": null,
"end_date": null,
};
};
componentDidMount(){
fetch("http://localhost:8000/api/profiles/")
.then(response => response.json())
.then(response => this.setState({ profiles: response}))
}
onChange = (e) => {
// Because we named the inputs to match their corresponding values in state, it's
// super easy to update the state
const state = this.state;
state[e.target.name] = e.target.value;
this.setState(state);
};
postData = (e) => {
e.preventDefault();
// Default options are marked with *
return fetch(url, {
body: JSON.stringify({status: 'submitted',
video_data: {material_id: this.state.material_id},
profile_data: {name: this.state.transcode_profile },
start: this.state.start_date,
end: this.state.end_date,
user: 'Lewis'}), // must match 'Content-Type' header
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, same-origin, *omit
headers: {
'user-agent': 'Mozilla/4.0 MDN Example',
'content-type': 'application/json'
},
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, cors, *same-origin
redirect: 'follow', // *manual, follow, error
referrer: 'no-referrer', // *client, no-referrer
})
.then(response => response.json()) // parses response to JSON
};
render() {
return (
<div>
<h2>Submit Job</h2>
<form onSubmit={this.postData}>
<label htmlFor="material_d">Material ID:</label>
<input id="material_id"
type="text"
name="material_id"
onChange={this.onChange}
required/>
<br/>
<label htmlFor={"transcode_profile"}>Transcode Profile:</label>
<ProfileList
onChange={this.onChange}
profiles={this.state.profiles}
/>
<br/>
<label htmlFor="start_date">Start Date:</label>
<input type="text"
name="start_date"
id="start_date"
onChange={this.onChange}
required/>
<br/>
<label htmlFor="end_data">End Date:</label>
<input type="text"
name="end_date"
id="end_date"
onChange={this.onChange}
required/>
<br/>
<button>Submit</button>
</form>
</div>
);
}
}
export default Submit_job;
Upvotes: 2
Views: 7432
Reputation: 3411
handleChange = (e, {value}) => {
this.setState({selectValue:value});
};
this can also be written as
handleChange = (e, data) => {
this.setState({selectValue:data.value});
};
For some elements Semantic-UI-React requires you to provide the event first but also a second argument which contains the data you need. It is a well known limitation.
Upvotes: 1
Reputation: 6884
The select should be passed the value as well, so it knows which option is selected:
const ProfileList = ({ onChange, profiles, value }) => (
<select
name="transcode_profile"
id="transcode_profile"
onChange={onChange}
value={value}
>
<option value="-----">----</option>
{profiles.map(profile => <option value={profile.name}>{profile.name}</option>)}
</select>
);
Then when rendering ProfileList, we should pass the selectValue state, as well as the handleChange callback.
<ProfileList
onChange={this.handleChange}
profiles={this.state.profiles}
value={this.state.selectValue}
/>
You should also set the default state in the constructor as well for selectValue
constructor(){
super();
this.state = {
"profiles": [],
"material_id": null,
"transcode_profile": null,
"start_date": null,
"end_date": null,
"selectValue": "-----"
};
}
If you haven't already read the React docs on forms, I would recommend them: https://reactjs.org/docs/forms.html#the-select-tag
Upvotes: 3