I am super new to React. Basically I have two components for now. My SearchInput-Component is a Select for cities, which does a real time search. It works super good and looks like this:
I added this component to my CityForm Component, which is a Search Form which I need to submit. And here I am stuck. For now I have just checked if submit works with a simple alert.
class CityForm extends React.Component {
handleSubmit(event) {
alert('Try tomorrow')
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<SearchInput placeholder="search city" style={{ width: 200 }} />
</form>
);
}
}
ReactDOM.render(
<CityForm />,
document.getElementById('react-form')
);
I was thinking that submit should be kind of a post request. For now my URL won't change when I submit and I kind of need to do the post request to some kind of URL. The url for post would be smth. like
filter?[city_id_eq]=02000000&commit=Search
Am I thinking right? But also, I will need to get the city_id from the Select, which will basically always have a value before submit. Should set the value of the state of handleSubmit to the value of the select and how do I do this?
Maybe it's relevant, that's what I render in SearchInput
render() {
const options = this.state.data.map(d => <Option key={d.value}>{d.text}</Option>);
return (
<Select
showSearch
value={this.state.value}
placeholder={this.props.placeholder}
style={this.props.style}
defaultActiveFirstOption={false}
showArrow={false}
filterOption={false}
onSearch={this.handleSearch}
onChange={this.handleChange}
notFoundContent={null}
>
{options}
</Select>
);
First You create a new value state in Your CityForm component and remove the value state from SearchInput component. In other words, lift the state up. Afterwards, You can update CityForm new value state in SearchInput via callback function. Something in the lines of:
https://symfonycasts.com/screencast/reactjs/callback-props
Then You will have the city id available in CityForm component's state.
Second, use use, e.g., Axios to make the form post request.
https://www.digitalocean.com/community/tutorials/react-axios-react#step-3-%E2%80%94-making-a-post-request
P.S. Look into React hooks once You get a little more comfortable with React components. ;)
Related
I'm trying to assign value to the hidden field in java script using the
JavaScript variable and trying to pass it back to the controller. The value every time I go in the post method for my model property DBErrorID is 0.
Razor View:
<body>
#Html.HiddenFor(model => model.DBErrorID, new { id = "DBErrorId" })
<input type="submit" value="Update" class="btn btn-success" onclick="GetValue()" />
</body>
JavaScript:
<script language="javascript" type="text/javascript">
function GetValue() {
$("#DBErrorId").val(totalValues);
// alert(totalValues);
}
<script>
Controller:
[HttpPost]
public ActionResult ErrorStatusView(Models.ErrorStatusModel obj)
{
Models.ErrorStatusModel objreg = new Models.ErrorStatusModel();
objreg.DBErrorID = obj.DBErrorID;
}
Your current server side code is creating an unnecessary new object of ErrorStatusModel as the first line, which will create a new object(objreg variable) with default values(unless you are setting it in a constructor), for an int type property it will be 0. If you are inspecting the values of objreg, that is the reason you see 0 as the property value.
You do not need to create this additional object. The model binder framework will create one for you and map the posted values, when you use ErrorStatusModel your method parameter type. That means your obj property is properly populated by the form data (assuming the DBErrorID property is settable)
[HttpPost]
public ActionResult ErrorStatusView(Models.ErrorStatusModel obj)
{
// obj is populated with form values.
// use obj
// return something.
}
Also, your client side code is trying to set the value of hidden input inside the GetValue method which is called on the onclick event of the submit button. If you are using a normal form submit and your button is inside a form tag, when user clicks on the submit button it will immediately submit the form (with the current value of that input)
If that is the case, you should prevent the default behavior (submitting the form) when the button is clicked, set the value as needded and fire the form submit via JavaScript.
There are multiple ways to do it. Here is one approach- the unobtrusive JavaScript approach- which assumes you have jQuery loaded to your page. Give an Id to the button, which we can use to wireup the click event.
<input type="button" value="Update" class="btn btn-success"
id="btn-save" />
Now in JavaScript, listen to the click event on this button, prevent the normal behavior(submitting the form), update the hidden input value and trigger the form submit.
$(function () {
$('#btn-save').click(function (e) {
e.preventDefault();
$("#DBErrorId").val(34);
$(this).closest("form").submit();
});
})
Also you should not create a new object in server
So, here is a weird behaviour I have noticed today.
I have a controller which inherits from SurfaceController.
I have a [Post] Action method which returns back to the same partial view and that's fine. The reason is due to paging/filtering that happens on that page.
Now, on the view itself, if I use a button submit, I see everything being submitted just fine.
However, if I use a hyperlink with an onclick event to set hidden field values and then do a form.submit(), initially the model has values which are null but then it re-executes the submit with the all of the values put in place again!
That doesn't make sense. What is the difference with a button submit and a javascript function doing a form.submit() ?
There really isn't much code:
// Controller
[HttpPost]
public PartialViewResult FilterResultsForTransaction(MyModel model)
{
.....
}
// View
<script language="javascript">
function ApplySort(fieldname, sortDir)
{
$('#Filter_FieldName').val(fieldname);
$('#Filter_SortDir').val(sortDir);
//var form = $('#form');
//form.submit();
}
</script>
<snip>
<input type="submit" onclick="javascript:ApplySort('OrderDate'........)" value="ASC" />
ASC
Now, if I don't use the submit button but just the hyperlink and comment in the form.submit() in the JS function - it does the post but the model values are null/default and then it recalls itself with the values populated again.
thoughts?!
When you click on the submit button, the page will submit its data BEFORE the script in ApplySort() is complete. So you will have to stop the submitting, then set your hidden field values, and then submit the form. Like this:
<input type="submit" data-field="bla" data-sort="ASC" value="Sort ASC" />
<script>
$("input").on("click", ApplySort)
function ApplySort(e)
{
e.preventDefault(); //stop postback
var btn = $(this);
var form = $('#form');
$('#Filter_FieldName').val(btn.attr("data-field"));
$('#Filter_SortDir').val(btn.attr("data-sort"));
console.log("submit")
form.submit();
}
</script>
Its generally bad to have script code in a onclick, so I bind the click event in my js code with jQuery.
Test it out here: http://jsfiddle.net/03gj1r02/2/
I am using ASP.Net MVC 4. I have multiple buttons on a view.. At present I am calling the same action method; and I am distinguishing the clicked button using a name attribute.
#using (Html.BeginForm("Submit", "SearchDisplay", new { id = Model == null ? Guid.NewGuid().ToString() : Model.SavedSearch }, FormMethod.Post))
{
<div class="leftSideDiv">
<input type="submit" id="btnExport" class="exporttoexcelButton"
name="Command" value="Export to Excel" />
</div>
<div class="pageWrapperForSearchSubmit">
<input type="submit" class="submitButton"
value="Submit" id="btnSubmitChange" />
</div>
}
//ACTION
[HttpPost]
public ActionResult Submit(SearchCostPage searchModel, string Command)
{
SessionHelper.ProjectCase = searchModel.ProjectCaseNumber;
if (string.Equals(Command, Constants.SearchPage.ExportToExcel))
{
}
}
QUESTIONS
Is there a way to direct to different POST action methods on different button clicks (without custom routing)?
If there is no way without custom routing, how can we do it with custom routing?
References:
Jimmy Bogard - Cleaning up POSTs in ASP.NET MVC
You can choose the url where the form must be posted (and thus, the invoked action) in different ways, depending on the browser support:
for newer browsers that support HTML5, you can use formaction attribute of a submit button
for older browsers that don't support this, you need to use some JavaScript that changes the form's action attribute, when the button is clicked, and before submitting
In this way you don't need to do anything special on the server side.
Of course, you can use Url extensions methods in your Razor to specify the form action.
For browsers supporting HMTL5: simply define your submit buttons like this:
<input type='submit' value='...' formaction='#Url.Action(...)' />
For older browsers I recommend using an unobtrusive script like this (include it in your "master layout"):
$(document).on('click', '[type="submit"][data-form-action]', function (event) {
var $this = $(this);
var formAction = $this.attr('data-form-action');
$this.closest('form').attr('action', formAction);
});
NOTE: This script will handle the click for any element in the page that has type=submit and data-form-action attributes. When this happens, it takes the value of data-form-action attribute and set the containing form's action to the value of this attribute. As it's a delegated event, it will work even for HTML loaded using AJAX, without taking extra steps.
Then you simply have to add a data-form-action attribute with the desired action URL to your button, like this:
<input type='submit' data-form-action='#Url.Action(...)' value='...'/>
Note that clicking the button changes the form's action, and, right after that, the browser posts the form to the desired action.
As you can see, this requires no custom routing, you can use the standard Url extension methods, and you have nothing special to do in modern browsers.
BEST ANSWER 1:
ActionNameSelectorAttribute mentioned in
How do you handle multiple submit buttons in ASP.NET MVC Framework?
ASP.Net MVC 4 Form with 2 submit buttons/actions
http://weblogs.asp.net/scottgu/archive/2007/12/09/asp-net-mvc-framework-part-4-handling-form-edit-and-post-scenarios.aspx
ANSWER 2
Reference: dotnet-tricks - Handling multiple submit buttons on the same form - MVC Razor
Second Approach
Adding a new Form for handling Cancel button click. Now, on Cancel button click we will post the second form and will redirect to the home page.
Third Approach: Client Script
<button name="ClientCancel" type="button"
onclick=" document.location.href = $('#cancelUrl').attr('href');">Cancel (Client Side)
</button>
<a id="cancelUrl" href="#Html.AttributeEncode(Url.Action("Index", "Home"))"
style="display:none;"></a>
This sounds to me like what you have is one command with 2 outputs, I would opt for making the change in both client and server for this.
At the client, use JS to build up the URL you want to post to (use JQuery for simplicity) i.e.
<script type="text/javascript">
$(function() {
// this code detects a button click and sets an `option` attribute
// in the form to be the `name` attribute of whichever button was clicked
$('form input[type=submit]').click(function() {
var $form = $('form');
form.removeAttr('option');
form.attr('option', $(this).attr('name'));
});
// this code updates the URL before the form is submitted
$("form").submit(function(e) {
var option = $(this).attr("option");
if (option) {
e.preventDefault();
var currentUrl = $(this).attr("action");
$(this).attr('action', currentUrl + "/" + option).submit();
}
});
});
</script>
...
<input type="submit" ... />
<input type="submit" name="excel" ... />
Now at the server side we can add a new route to handle the excel request
routes.MapRoute(
name: "ExcelExport",
url: "SearchDisplay/Submit/excel",
defaults: new
{
controller = "SearchDisplay",
action = "SubmitExcel",
});
You can setup 2 distinct actions
public ActionResult SubmitExcel(SearchCostPage model)
{
...
}
public ActionResult Submit(SearchCostPage model)
{
...
}
Or you can use the ActionName attribute as an alias
public ActionResult Submit(SearchCostPage model)
{
...
}
[ActionName("SubmitExcel")]
public ActionResult Submit(SearchCostPage model)
{
...
}
you can use ajax calls to call different methods without a postback
$.ajax({
type: "POST",
url: "#(Url.Action("Action", "Controller"))",
data: {id: 'id', id1: 'id1' },
contentType: "application/json; charset=utf-8",
cache: false,
async: true,
success: function (result) {
//do something
}
});
suppose i have one form and form has two div container. one div container has few textboxes for submiting login details and another div also has few textboxes those related to register. now my home controller has two action method one is login and another is register. i want that when user click on login button then i will submit form through jquery but before submit i will change action url. the same way i want to call register action method when user click on register button. please guide me how could i do this in mvc with jquery. please help me with sample code.
another person answer like in other forum.
#model MvcForums.Models.StudentModel
#{
using(#Html.BeginForm("Create","Student", FormMethod.Post))
{
<label> Name</label>
#Html.TextBoxFor(m=>m.FirstName) <br/>
<label> From country:</label>
#Html.DropDownListFor(m=>m.CountryId, Model.Countries,"--please select-- ") <br/>
<input id="btnSave" value ="Login" type="submit" name="commandName"/>
<input id="btnRegister" value ="Register" type="submit" name="commandName"/>
}
}
[HttpPost]
public ActionResult Create(StudentModel studentModel, string commandName)
{
if(commandName == "Login")
{
}
else if(commandName == "Register")
{
}
return View("Index");
}
after reading his answer some confusion occur in my mind because i am newbie in mvc and those are as follows
first of all ur code is not readable for ill format. i am new in mvc....just learning it. after reading ur code some confusion occur.
1) why extra bracket u gave #{ }
2 u use <label> Name</label> in form building code. in html4 is there any tag ? is it html5 specific tag ?
3) #Html.DropDownListFor(m=>m.CountryId, Model.Countries,"--please select-- ")
when u building dropdown why u did not specify value & text filed.......how mvc can understand what field will be value & what will be text ? u just bind the model with DropDownListFor()
4) just see it
<input id="btnSave" value ="Login" type="submit" name="commandName"/>
<input id="btnRegister" value ="Register" type="submit" name="commandName"/>
both the button name is commandName ? is it correct ?
when user click on any button then how button name will be pass to
public ActionResult Create(StudentModel studentModel, string commandName)
Create() method ? please tell me how implicitly command name will be pass to Create() and how commandName variable at server side can hold the button name.
i have too much confusion after reading ur code. if possible please discuss all my points in details. thanks
i want that when user click on login button then i will submit form
through jquery but before submit i will change action url. the same
way i want to call register action method when user click on register
button.
1. Event on button click:
$(function(){
$("#btnSave").click(function(){
$("#btnSave").closest("form").attr("action", "/home/test");
});
});
2. MarkUp:
<form method="POST" action="/home/test1" >
<input id="btnSave" value="Login" type="submit" name="commandName"/>
</form>
3. Server side:
[HttpPost]
public ActionResult Test(string commandName)
{
return null;
}
1) Razor syntax reference http://haacked.com/archive/2011/01/06/razor-syntax-quick-reference.aspx
2) The <label> is not specific html5 tag but it have additional attribute in html5, http://www.w3schools.com/tags/tag_label.asp
3) You can build your IEnumerable of SelectListItem in which specified Text and Value
4) The input name commandName is not important if you don't want to catch client value value ="Login" on server side,
I've got an mvc4/jquerymobile application, and I'm having a hard time figuring out why, after returning a RedirectToRoute(rvd) from a controller-action, the redirected-to url is not shown.
I start the process on an Edit page with a form at http://localhost/Report/Params/9. I edit the form, submit it, and the Report controller, Params [HttpPost]action fires up. It validates the form values, munges them around a bit, and then adds the lot of them to a RouteValueDictionary, along with my controller ("Report") and new action ("Render") properties.
This all happens correctly, and I'm taken to the "Render" view, but the URL displayed in the browser remains http://localhost/Report/Params/9
I would like the browsers url to show http://localhost/Report/Params/9?p1=1&p2=2&p3=3 instead, because I want the users to be able to bookmark a parameter-set for later use.
What am I missing? I think the issue is related to jquerymobile's handling of the submit button click. I tried to mitigate that with data-ajax=false, but it doesn't seem to have helped any.
<button type="submit" data-theme="b" name="submit" value="submit-value" data-ajax="false">
Submit
</button>
Thanks
Edit: Here's a close replica of my redirecting function...
public ActionResult Params(FormCollection Params ) {
RouteValueDictionary rvd = new RouteValueDictionary();
// example values //
rvd.Add("controller", "Report");
rvd.Add("action", "Render");
rvd.Add("id", 10);
rvd.Add("p1", 1);
rvd.Add("p2", 2);
rvd.Add("p3", 3);
RedirectToRouteResult rrr = RedirectToRoute(rvd);
return rrr;
}