This onChange event handles the selection of a dataschema then makes a subsequent request to get the queryschemas of the selected dataschema. handleChange is working correctly and renders the appropriate querySchemas in a dropdown list.
handleChange = (e) => {
const dataSchema = this.state.dataSchemas.find(dataSchema => dataSchema.name === e.target.value);
if (dataSchema) {
axios({
method: 'get',
url: `${dataSchema.selfUri}/queryschemas/`,
headers: { 'Accept': "" }
})
.then(response => {
console.log(response)
console.log(JSON.stringify(dataSchema.selfUri));
console.log(dataSchema.id)
this.setState({
querySchemaId: response.data.data[0].id,
querySchemaUri: response.data.data[0].selfUri,
querySchemaName: response.data.data[0].name,
querySchemas: response.data.data, //has list of querySchemas from request
selectedId: dataSchema.id
}, () => {
console.log(this.state.querySchemaId)
console.log(this.state.querySchemaUri)
console.log(this.state.querySchemaName)
console.log(this.state.selectedId)
});
})
.catch(error => console.log(error.response));
}
}
//This is the list of querySchemas returned by the above request
{
"data" : [ {
//array postion [0] --
"id" : "2147483601",
"selfUri" : "/dataschemas/2147483600/queryschemas/2147483601",
"name" : "QS-1"
}, {
//array position [1]
"id" : "2147483602",
"selfUri" : "/dataschemas/2147483600/queryschemas/2147483602",
"name" : "QS-2"
} ]
}
querySchemaChange = e => {
const querySchema = this.state.querySchemas.find(querySchema => querySchema.name === e.target.value);
if (querySchema) {
axios({
method: 'get',
url: `/dataschemas/${this.state.selectedId}/queryschemas/${this.state.querySchemaId}/queries`, //<--- {this.state.querySchemaId} is not updating to show the current querySchema that is selected
headers: { "Accept": "" }
})
.then(response => {
console.log(response)
})
.catch(error => console.log(error.response));
}
}
Then the second call is using the querySchemaId to make a request to the specific URI,
But querySchemaId: response.data.data[0].id, always grabs the first array from the response, obviously. So my issue is if I choose a different querySchema from the drop down it is always using the response in position [0] to make the next call. How can I keep the name that is selected updated in state and use the id attached to it, so it fires the right request?
These are the select elements rendering the dropdowns
render(){
return (
<label>
Pick a DataSchema to filter down available QuerySchemas:
<select value={this.state.value} onChange={this.handleChange}>
{dataSchemas &&
dataSchemas.length > 0 &&
dataSchemas.map(dataSchema => {
return <option value={dataSchema.name}>{dataSchema.name}</option>;
})}
</select>
</label>{" "}
<br />
<label>
Pick a QuerySchema to view its corresponding queries status:
<select value={this.state.querySchemaName} onChange={this.handleChange} onChange={this.querySchemaChange}>
{querySchemas &&
querySchemas.map(querySchema => {
return <option value={querySchema.name}>{querySchema.name}</option>;
})}
</select>
</label>{" "}
<br />
)
}
You forgot to save selected value in the state (for select) and use event data (id) directly (in query url), not from state (setState is async, it will be updated later):
querySchemaChange = e => {
const querySchema = this.state.querySchemas.find(querySchema => querySchema.name === e.target.value);
if (querySchema) {
const {id, name} = querySchema
this.setState({
querySchemaId : id,
querySchemaName: name
});
axios({
method: 'get',
url: `/dataschemas/${this.state.selectedId}/queryschemas/${id}/queries`,
querySchemaName is used for current select value.
Is saving querySchemaId needed now (not used in query)? Is it used elsewhere?
Related
I have following Table / Array:
If I press the blue button, then all items with the same group as the record should change the Status (Gratis).
But now it just change the Value of the Record and all items above it. As an example, if I press the Button on Record No. 1 then itselft and all above (No. 0) get an change of the Status (Gratis).
Following code im using to go through the array and change the Status:
private _updateFreeStatus = (record: QuestionModel): void => {
fetch('api/Test/UpdateGratisStatus', {
headers: { 'Content-Type': 'application/json' },
method: 'PUT',
body: JSON.stringify({
'group': record.group,
'free': record.free,
})
});
this.state.question.map(item => {
if (item.group === record.group)
{
item.free = !record.free;
}
});
}
do not mutate the state
create a copy, and use setState
Use
const updatedQuestions = this.state.question.map(item => {
if (item.group === record.group) {
return {
...item,
free: !record.free
}
}
return item;
});
this.setState({question: updatedQuestions});
I am trying to write a react code to submit the value to the backend server.
I want the input field to be cleared out as soon as the user hits submit button.
I have written the below code, could anyone help me with what I am missing here?
class Create extends Component {
state = {
task : {
title: '',
completed: false
}
}
CreateHandler = (event) => {
this.setState((state) => {
return {
task: {
...state, title: '' // <----- CLEARING HERE (well, trying)
}
}
});
event.target.value=""; // <----- ALSO HERE
event.preventDefault();
axios({
method:'post',
url:'http://localhost:8000/api/task-create',
data: this.state.task,
xsrfHeaderName: this.props.CSRFToken
})
.then((res) => {
console.log(res.data);
})
this.props.updateState(this.state.task)
}
ChangeHandler = (event) => {
this.setState(state => {
return {
task: {
...state, title: event.target.value
}
}
})
}
Breaking the code in parts so that it's easily readable.
render() {
return (
<form onSubmit={this.CreateHandler.bind(this)}>
<div className="header form-group">
<input
className="newItem form-control"
onChange={this.ChangeHandler.bind(this)}
value={this.state.task.title}
/>
<button
type="submit"
class="saveButton btn btn-primary btn-warning">
submit
</button>
</div>
</form>
)
}
}
export default Create;
The end goal is to clear the input field and then send the data to the backend django server, which is being done successfully except the input field being cleared.
You are not updating state correctly
this.setState((state) => {
return {
task: {
...state, title: '' // <----- CLEARING HERE (well, trying)
}
}
});
should be
this.setState((state) =>({...state, task: {...state.task, title: ''}}))
In your case, it could be done like this:
this.setState(previousState => ({
task: {
...previousState.task,
title: '' // <----- CLEARING HERE
}
}));
A better way to write your createHandler method:
CreateHandler = (event) => {
// Prevent the default form action
event.preventDefault();
// Call your API
axios({
method: "post",
url: "http://localhost:8000/api/task-create",
data: this.state.task,
xsrfHeaderName: this.props.CSRFToken,
}).then((res) => {
// Request passed
// Call your prop function
this.props.updateState(this.state.task);
// Clear the unnecessary data
this.setState((prevState) => ({
// Create new object
task: {
// Assign the properties of previous task object
...prevState.task,
// Clear the title field
title: "",
},
}));
});
};
Hope this helps!
I make a component, which show information from database in table. But this information with filters.
Filtering can be by event type and by participant (id: integer type).
When I click the button, I call handleShowClick(). In this function I check: if value of type event isn't null, I get from database events with this type. if value of type event is null, I get all events.
After this I check a participant value. If value isn't null, I call function, which search which events are include this participant. Data from this.state.event show in table in another component.
I haven't problems with event type. But I have problem with participant. When I choose one of participant, table shows correct data for a split second. After this return to prev state (without filter by participants).
How can I fix this issue? I set state to event only in this component
class TestPage extends Component {
constructor(props) {
super(props);
this.state = {
event: [],
searchByType: null,
searchByParticipant: null,
participantToEvent: []
};
this.handleShowClick = this.handleShowClick.bind(this);
this.onHandleEventByTypeFetch = this.onHandleEventByTypeFetch.bind(this);
this.handleParticipantSearch = this.handleParticipantSearch.bind(this);
this.onHandleEventFetch = this.onHandleEventFetch.bind(this);
}
handleShowClick() { // onClick
if (this.state.searchByType !== null) {
this.onHandleEventByTypeFetch(); // select * from ... where type=...
} else {
this.onHandleEventFetch(); // select * from ...
}
if (this.state.searchByParticipant !== null) {
this.handleParticipantSearch();
}
}
handleParticipantSearch() {
const list = [];
this.state.participantToEvent.map(itemP => { // participantToEvent is binding table
if (itemP.parid === this.state.searchByParticipant) {
this.state.event.map(itemEvent => {
if (itemEvent.id === itemP.eventid) {
list.push(itemEvent);
}
});
}
});
console.log(list); // here I see array with correct result
this.setState({ event: list });
}
onHandleEventFetch() {
fetch( ... , {
method: 'GET'
})
.then((response) => {
if (response.status >= 400) {
throw new Error('Bad response from server');
}
return response.json();
})
.then(data => {
if (data.length === 0) {
alert('nothing');
} else {
this.setState({
event: data
});
}
});
}
onHandleEventByTypeFetch() {
fetch( ... , {
method: 'GET'
})
.then((response) => {
if (response.status >= 400) {
throw new Error('Bad response from server');
}
return response.json();
})
.then(data => {
if (data.length === 0) {
alert('nothing');
} else {
this.setState({
event: data
});
}
});
...
}
}
Structure of this.state.event:
[{id: 1, name: 'New event', participant: 5, type: 10}, ...]
Structure of this.state.participantToEvent:
[{id: 1, idparticipant: 5, idevent: 1}, ...]
this.setState(...this.state,{ event: list });
I think this would solve your problem. Because you clear every item except for {event:list} by not copying the previous state.
Edit:
You should put
...this.state
to onHandleEventByeTypeFetch and onHandleEventFetch. Without them when you click handleShowClick one of those two functions always work and clears searchByParticipant data from the state by not copying the previous state.
The reason for you see the correct data for a short time is all about async nature of the state.
I am newbie on ReactJS, I want to get a Price value just after the select of the Product name by react select and display it.
My method :
constructor(props) {
super(props);
this.state = {
PrixV: ""
}
PrixDisplay(selectprdt) {
return axios.get("/app/getPrixprod/" + selectprdt).then(response => {
if (response && response.data) {
this.setState({
PrixV: response.data
});
}
console.log(response.data)
}).catch(error => {
console.error(error);
});
}
I try to read this value by :
<p>{this.state.PrixV} </p>
When I run it, nothing is displayd on the Price column and after I select the product name, I get :
Objects are not valid as a React child (found: object with keys {PrixV}). If you meant to render a collection of children, use an array instead.
in p (at AjouterFacture.js:383)
And the console returns :
[{…}]0: {PrixV: "250.000"}length: 1__proto__: Array(0)
How can I read and display it ?
You must use the map, try to change the code like this :
constructor(props) {
super(props);
this.state = {
Prix: []};
render() {
let {
Prix
} = this.state.Prix;
return (
<td>
{ this.state.Prix.map((pr, k) =>
<p key={k} >{pr.PrixV} </p>
)}
</td>
);}
PrixDisplay(selectprdt) {
return axios.get("/app/getPrixprod/" + selectprdt).then(response => {
if (response && response.data) {
this.setState({
Prix: response.data
});
}
}).catch(error => {
console.error(error);
});
}
I hope that's will be helpful.
constructor(props) {
super(props);
this.state = {
mydata: ''
};
productNameSelected(selectprdt) {//not sure from where you will get selectprdt variable , but something like this will work
axios.get("/app/getPrixprod/" + selectprdt).then(response => {
if (response && response.data) {
this.setState( {mydata : response.data});
}
console.log(response.data)
})
}
<p>{this.state.mydata} </p> //my data should not be a object , so you need to make string if you wnat to directly use it here
Edit
I can see you are able to get the response , but react still gives error:-
change the paragrah code to
<p>{this.state.PrixV[0].PrixV} </p>
Or The good way will be to set the data properly so
let paragrah be same
<p>{this.state.PrixV} </p>
PrixDisplay(selectprdt) {
return axios.get("/app/getPrixprod/" + selectprdt).then(response => {
if (response && response.data && response.data[0]) {
this.setState({
PrixV: response.data[0].PrixV
});
}
console.log(response.data)
}).catch(error => {
console.error(error);
});
}
You are getting the error because currently you are getting PrixV as an array(object) not a primitive data type.
Hope this solves the issue.
The dropdown list renders properly but when clicked on a dropdown result, nothing happens. I know that select2 expects the results to be in a certain way but couldn't figure out why the results won;t get selected when clicked on the result in the dropdown. No errors or anything in the console..
The response from the REST service is an array of objects with Person details.
Here's a jsfiddle that I have setup to illustrate the problem: https://jsfiddle.net/qygpb1Lr/
const $select2 = this.$element.find((`[rel='${this._interestedPartySelect2_id}']`));
const formatResult = person => {
if (!person || !person.FULL_NAME) return '';
return `
<strong>${person.LAST_NAME}, ${person.FIRST_NAME}</strong>
<br />
<i class='txt-color-cernerPurple'>${person.JOBTITLE || '--'}</i>
<br />
<span style="color:#525564">${person.DEPARTMENT || '--'}</span>
<br />
<span class='text-muted'>${person.INTERNET_E_MAIL || '--'}</span>
`;
};
const formatSelection = person => {
if (!person || !person.LAST_NAME || !person.FIRST_NAME) return '';
return `${person.LAST_NAME}, ${person.FIRST_NAME}`;
};
$select2.select2({
placeholder : 'Enter Last Name',
allowClear : true,
minimumInputLength : 3,
query: query => {
$.ajax({
url : `/remedy/people/last_name/${query.term}`,
type : 'GET',
headers: { 'content-type': 'application/json' },
data : JSON.stringify({ searchTerm: query.term })
})
.done(people => {
query.callback({ results: people });
});
},
formatResult,
formatSelection,
escapeMarkup : m => m
})
.on('select2-removed', e => {
// TODO
})
.on('select2-selecting', e => {
console.log(e); // TODO: Remove this
if (e.object && e.object.PERSON_ID) {
console.log(e.object.PERSON_ID); // TODO
}
});
I resolved this myself by passing an ID field to the select2 options like-so:
$select2.select2({
placeholder : 'Enter Last Name',
allowClear : true,
minimumInputLength : 3,
id: obj => obj.PERSON_ID,
query: query => {
$.ajax({
url : `/remedy/people/last_name/${query.term}`,
type : 'GET',
headers: { 'content-type': 'application/json' },
data : JSON.stringify({ searchTerm: query.term })
})
.done(people => {
query.callback({ results: people });
});
},
formatResult,
formatSelection,
escapeMarkup : m => m
})
.on('select2-removed', e => {
// TODO
})
.on('select2-selecting', e => {
console.log(e); // TODO: Remove this
if (e.object && e.object.PERSON_ID) {
console.log(e.object.PERSON_ID); // TODO
}
});