I am trying to convert my Jquery code to React. I have a form that when submitted creates multiple post requests to different sites and generates data for each site in a "card" corresponding to each site.
I made a component for the form. I also have a handleSubmit event but that only makes one fetch request. I want to make multiple fetch requests to multiple sites with one button click.
handleSubmit(event) {
event.preventDefault();
this.setState({
input: event.target.value
})
const data = new FormData(event.target);
fetch('/d2s2/L1000', {
method: 'POST',
body: data
})
}
render () {
return (
<div>
<form class="form-inline" role="form">
<div class="form-group" style="text-align:center;">
<select id="memoryType" class="form-control firstList">
<option value="drug" selected="selected">Drug</option>
<option value="disease">Disease</option>
</select>
</div>
<div class="form-group">
<select id="drugInput" class="form-control search-input secondList" name="drug">
</select>
</div>
<button class="form-control" id="submit"><i class="fas fa-search"></i></button>
</form>
</div>
)
}
this is my Jquery:
$("#submit").click(function(e) {
var selectedOption = $('#memoryType option:selected').val();
var text= $("#drugInput option:selected").val();
var search = JSON.stringify({"input": text});
$('.post-load').show();
if (selectedOption.toLowerCase() == "drug") {
$.post("/d2s2/L1000", search, function(data) {
console.log(data);
$(".card-1").html(data);
$('.loader1').fadeOut('fast');
}).fail( function(xhr, textStatus, errorThrown) {
$(".card-1 .card-text").html("No significant signatures found");
$('.loader1').fadeOut('fast');
})
$.post("/d2s2/creeds_drugs", search, function(data) {
console.log(data);
$(".card-2").html(data);
$('.loader2').fadeOut('fast');
}).fail( function(xhr, textStatus, errorThrown) {
$(".card-2 .card-text").html("No significant signatures found");
$('.loader2').fadeOut('fast');
})
$.post("/d2s2/creeds_diseases", search, function(data) {
console.log(data);
$(".card-3").html(data);
$('.loader3').fadeOut('fast');
}).fail( function(xhr, textStatus, errorThrown) {
$(".card-3 .card-text").html("No significant signatures found");
$('.loader3').fadeOut('fast');
})
$.post("/d2s2/geneshot", search, function(data) {
console.log(data);
$(".card-4").html(data);
$('.loader4').fadeOut('fast');
}).fail( function(xhr, textStatus, errorThrown) {
$(".card-4 .card-text").html("No significant signatures found");
$('.loader4').fadeOut('fast');
})
When I click on the submit button, all the cards should make post requests to their respective endpoints.
You can declare a state for each site you are requesting to and handle the requests separately like this:
state = {
site1: {},
site2: {}
}
requestSite1 = data => {
fetch('site1Url', {
method: 'POST',
body: data
}).then(res => this.setState({ site1: res }))
}
requestSite2 = data => {
fetch('site2Url', {
method: 'POST',
body: data
}).then(res => this.setState({ site2: res }))
}
async handleSubmit(event) {
event.preventDefault();
this.setState({
input: event.target.value
})
const data = new FormData(event.target);
await this.requestSite1(data);
await this.requestSite2(data);
}
and pass the states as props to your Card component like:
<Card site1Data={this.state.site1} site2Data={this.state.site2} />
Related
I try to make an cascading dropdown, but I have problems with the sending and fetching of the response data.
Backend:
[HttpPost]
public async Task<JsonResult> CascadeDropDowns(string type, int id)
{ .............
return Json(model);
}
Here I get the correct data.
First I tried:
$("#dropdown").change( function () {
var valueId = $(this).val();
var name = $(this).attr("id");
let data = new URLSearchParams();
data.append("type", name);
data.append("id", valueId);
fetch("#Url.Action("CascadeDropDowns", "Home")", {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
},
body: data
})
.then(response => {
console.log('Success:', response);
return response.json();
})
.then(json => {
console.log('Success:', json );
console.log('data:', json.Projects);
PopulateDropDown("#subdropdown1",json.Projects)
})
.catch(error => {
console.log('Error:', error);
});
});
Here I can send the Request and get a "success" back. However, when I access json.Projects I just get an `undefined. I have tried to change the Content-Type, without success.
Secondly I have used:
$.ajax({
url: "#Url.Action("CascadeDropDowns", "Home")",
data: data,
type: "POST",
contentType: "application/x-www-form-urlencoded;charset=UTF-8",
success: function (data) {
console.log(data);
},
error: function (r) {
console.log(r.responseText);
},
failure: function (r) {
console.log(r.responseText);
}
});
With this I get an Illegal Invocation Error.
What do I have to do that get either of those working? What are their problems?
I try to make an cascading dropdown, but I have problems with the
sending and fetching of the response data.What do I have to do that get either of those working? What are their problems?
Well, let consider the first approach, you are trying to retrieve response like json.Projects but its incorrect because data is not there and you are getting undefined as below:
Solution:
Your response would be in json instead of json.Projects
Complete Demo:
HTML:
<div class="form-group">
<label class="col-md-4 control-label">State</label>
<div class="col-md-6">
<select class="form-control" id="ddlState"></select>
<br />
</div>
</div>
Javascript:
var ddlState = $('#ddlState');
ddlState.empty();
ddlState.append($("<option></option>").val('').html('Please wait ...'));
let data = new URLSearchParams();
data.append("type", "INDIA");
data.append("id", 101);
fetch("http://localhost:5094/ReactPost/CascadeDropDowns", {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
},
body: data
})
.then(response => {
return response.json();
})
.then(result => {
console.log(result);
var ddlState = $('#ddlState');
ddlState.empty();
ddlState.append($("<option></option>").val('').html('Select State'));
$.each(result, function (index, states) {
ddlState.append($("<option></option>").val(states.cityId).html(states.cityName));
});
})
Second approach:
In ajax request you are passing object as object fahsion like data: data whereas, your controller expecting as parameter consequently, you are getting following error:
Solution:
You should pass your data within your ajax request like this way data: { type: "YourTypeValue", id:101 }, instead of data: data,
Complete Sample:
$.ajax({
url: 'http://localhost:5094/ReactPost/CascadeDropDowns',
type: 'POST',
data: { type: "YourValue", id:101 },
success: function (response) {
ddlState.empty();
ddlState.append($("<option></option>").val('').html('Select State'));
$.each(response, function (i, states) {
ddlState.append($("<option></option>").val(states.cityId).html(states.cityName));
});
},
error: function (response) {
alert('Error!');
}
});
Note: I have ommited contentType because, by default contentType is "application/x-www-form-urlencoded;charset=UTF-8" if we don't define.
Output:
I just started web development on ASP.NET Core a while ago and learnt about ReactJS integration with ASP.NET Core and this is what I am facing right now.
Issues Description
So, I have a front-end login form that looks like this.
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: ''
};
// binding that allows for callbacks when the form is submitted
this.handleChange = this.handleChange.bind(this);
this.handleLogin = this.handleLogin.bind(this);
}
handleChange({ target }) {
this.setState({
[target.name]: target.value
});
}
handleLogin() {
if (this.state.username === '' || this.state.password === '') {
alert('Missing username or password!');
} else {
$.ajax({
type: 'POST',
url: '/Home/IsAuthenticate/',
contentType: 'application/json',
cache: true,
data: JSON.stringify(
{
"Name": this.state.username,
"Password": this.state.password
}),
success: function (data, textStatus, jQxhr)
{
console.log("Welcome Admin");
alert("Welcome Admin!");
}.bind(this),
error: function (xhr, textStatus, error)
{
console.log("error");
alert("Error!");
alert(xhr.responseText);
}.bind(this)
});
}
}
render() {
return (
<div className="home-page">
<h1>Centre Booking</h1>
<br />
<form>
<input
type="text"
id="username"
name="username"
placeholder="Username"
onChange={this.handleChange}
/>
<br />
<input
type="password"
id="password"
name="password"
placeholder="Password"
onChange={this.handleChange}
/>
<br />
<button
id="loginBtn"
onClick={this.handleLogin}
>
Login
</button>
</form>
</div>
);
}
}
Basically, the issue is that when I tried to click on the Login Button after I input some data on username and password field so that it will call '/Home/IsAuthenticate/' in the HomeController for the request through AJAX, the website will not trigger any of the alert function. Even when IsAuthenticate in my HomeController is returning Ok();
Here is my code for the controller.
[HttpPost]
public IActionResult IsAuthenticate([FromBody] UserAPI user)
{
RestClient restClient = new RestClient(APPLICATION_LAYER_URL);
// DEBUG
System.Diagnostics.Debug.WriteLine("Username: " + user.Name + ", Password: " + user.Password);
RestRequest authenticateRequest = new RestRequest("api/centre-application-layer/authenticate", Method.Post);
authenticateRequest.AddJsonBody(user);
RestResponse authenticateResponse = restClient.Execute(authenticateRequest);
if (authenticateResponse.IsSuccessful)
{
System.Diagnostics.Debug.WriteLine("Successful authenticate request");
// return Ok(JsonConvert.DeserializeObject<string>(authenticateResponse.Content));
return Ok(); // this does not work either
}
else
{
System.Diagnostics.Debug.WriteLine("BadRequest authenticate request");
return BadRequest(JsonConvert.DeserializeObject<string>(authenticateResponse.Content));
}
}
As you can see, I wrote a System.Diagnostics.Debug.WriteLine in the code above to figure out the endpoint of the program and this is the result. Therefore, it means that the request is Successful.
But after I clicked on the Login Button, this is what I am seeing from the browser. No alert that says "Welcome Admin" is shown on the webpage as expected in my ReactJS code above.
Trying To Reproduce The Issue
But strangely enough, I did try to reproduce the issue by creating a simple function, SomethingPost which return a plain Ok(). But it is working as expected. Which means I failed to reproduce it.
Here is my handleLogin() function. Basically, everything else in my ReactJs code is same except for the url in AJAX. Instead of '/Home/IsAuthenticate' it is now 'Home/SomethingPost/'
handleLogin() {
if (this.state.username === '' || this.state.password === '') {
alert('Missing username or password!');
} else {
$.ajax({
type: 'POST',
url: '/Home/SomethingPost/',
contentType: 'application/json',
cache: true,
data: JSON.stringify(
{
"Name": this.state.username,
"Password": this.state.password
}),
success: function (data, textStatus, jQxhr) {
console.log("Welcome Admin");
alert("Welcome Admin!");
}.bind(this),
error: function (xhr, textStatus, error) {
console.log("error");
alert("Error!");
alert(xhr.responseText);
}.bind(this)
});
}
}
Here is my SomethingPost function in HomeController
[HttpPost]
public IActionResult SomethingPost([FromBody] UserAPI user)
{
return Ok();
}
This is the result on the webpage. As you can see, it is now giving me alert "Welcome Admin"
Summary
I tried to make the description as detail as I possible could so it can also be reproducable by others. But according to the StackOverflow Question Guidelines one should not copy-paste the entire program. So, if it could be useful, here is the link to my project:
https://github.com/Calmen00-code/Centre-Booking-Web-App
Please give me advise if there is any improvement that I can make for my question. Thanks!
I have a function that gets the form values and send them Flask backend to retrieve info from SQLite database. I'm using jQuery $.ajax() with POST to allow for better error handling.
Because the ajax is async I'm passing a callback to logTable(callback) as suggested here. I need the logTable() to run after I input the form data and click the submit button. I'm using $("#some-id").click() to achieve this.
const logsTable = (callback) => {
const startDate = $("#start-date").val();
const endDate = $("#end-date").val();
const container = $("#programs").val();
const server = window.location.host;
const url = `http://${server}/api/log-info`;
let logs = "";
let dataToSend = {
start_date: startDate,
end_date: endDate,
program: container,
};
$.ajax({
type: "POST",
url: url,
data: dataToSend,
success: (data) => {
callback(data);
},
error: (jqXHR, textStatus, errorThrown) => {
alert(errorThrown);
},
});
};
$("#submit-button").click(() => {
return logsTable((data) => {
$("#logs-div").html(data);
alert("Success");
});
});
I receive the alert with Success, the data briefly appears on the page and disappears. If run the code below directly it, it runs on page reload and posts an empty list to a page because no data was sent to the backend.
logsTable((data) => {
$("#logs-div").html(data);
alert("Success");
});
I need to somehow the function call above to a Submit button. How can I do that?
I'm new to react I've cobbled this react component together from different pieces i've found on the web. It's supposed to upload a file via ajax on submit. For some reason it's double firing. So when I hit submit my server is getting two requests instead of one.
Does anything stand out that a react beginner might miss?
/** #jsx React.DOM */
var $ = require("jquery")
var React = require('react');
var FileForm = React.createClass({
getInitialState: function() {
return {
myFileName: "",
myFileHandle: {}
};
},
handleChange: function(event) {
this.setState({
files: [event.target.files[0]] // limit to one file
});
},
handleSubmit: function(e) {
e.preventDefault();
var data = new FormData();
$.each(this.state.files, function(i, file) {
data.append('file-'+i, file)
})
$.ajax({
url: "/api/content/csv/upload.json",
data: data,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(data) {
this.refs.fileInput.value = null
console.log(this.refs.fileInput)
console.log(data)
}.bind(this),
error: function(xhr, status, err) {
console.log(xhr)
console.log(status)
console.log(err)
}.bind(this)
})
},
render: function() {
return (
<form onSubmit={this.handleSubmit} method="POST" encType="multipart/form-data">
<input ref="fileInput" type="file" onChange={this.handleChange}/>
<input type="submit" value="Submit"/>
</form>
)
}
})
module.exports = FileForm
I am working thought the Reactjs Tutorial. I am trying to understand how the CommentForm component submits (or updates the server) with the data it has collected via passing it up to the CommentBox.
Here are the two components that work for reference:
var CommentForm = React.createClass({
handleSubmit: function(e) {
e.preventDefault();
var author = React.findDOMNode(this.refs.author).value.trim();
var text = React.findDOMNode(this.refs.text).value.trim();
if (!text || !author) {
return;
}
this.props.onCommentSubmit({author: author, text: text});
React.findDOMNode(this.refs.author).value = '';
React.findDOMNode(this.refs.text).value = '';
return;
},
render: function() {
return (
<form className="commentForm" onSubmit={this.handleSubmit}>
<input type="text" placeholder="Your name" ref="author" />
<input type="text" placeholder="Say something..." ref="text" />
<input type="submit" value="Post" />
</form>
);
}
});
var CommentBox = React.createClass({
loadCommentsFromServer: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
cache: false,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
handleCommentSubmit: function(comment) {
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'POST',
data: comment,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
getInitialState: function() {
return {data: []};
},
componentDidMount: function() {
this.loadCommentsFromServer();
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
},
render: function() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
</div>
);
}
});
My source of confusion comes from handleCommentSubmit in the CommentBox component, specifically the Ajax success callback.
Since we set data: comment, data is now merely the comment the form collected. But on success we take data and do this.setState({data: data});. Wouldn't that be setting the state to only one comment (the one we collected in the form?). Wouldn't we need to pull from the server to get all of the data, including the POST we just made with something like loadCommentsFromServer? How does this work?
Since we set data: comment, data is now merely the comment the form
collected. But on success we take data and do this.setState({data:
data});. Wouldn't that be setting the state to only one comment (the
one we collected in the form?).
No, in the example, the comment passed in to the function is setting the data property for the ajax request. The data parameter in the success callback is the data from the ajax response.
So, here they are setting the data state property to whatever the server responds with. I think the example assumes that the server is reflecting the same comment, but this allows the server to save the comment during the HTTP call.