Add onsubmit event to call JS function in MVC3 - c#

I have a problem with calling JS method from form in MVC3 project: I have a "search"page without forms with two buttons - Search and Cancel. Click on search runs JS function runSearch in ProductDefinition.
<div id="productSearch-dialog" class="modal fade" style="width: 1000px; display: none">
<div class="modal-header">
<button class="close" aria-hidden="true" data-dismiss="modal" type="button">×</button>
<h3>Search Results</h3>
</div>
<div class="modal-body" style="height: 650px;">
<div>
<input id="inputname" type="text" /><font class="red-font" id="lblrequired" style="display: none">*</font>
</div>
<div id="searchresultcontain" class="grid">
</div>
<div id="Pagination" class="pagination">
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" onclick="productDefinition.runSearch();">Search</button>
<button class="btn btn-primary" data-dismiss="modal">Cancel</button>
</div>
How can I run this JS method (runSearch) when I press ? As far as I understand, this will be onsubmit event which is form event, so I am need to add form element with onsubmit property. I tried surrounding input field with BeginForm helper method:
#using (Html.BeginForm(new { onsubmit = "productDefinition.runSearch();" }))
{
<input id="inputname" type="text" /><font class="red-font" id="lblrequired" style="display: none">*</font>
<input type="submit" value="Submit" style="visibility: hidden" />
}
but it does not seem to be working - when I press enter I for some reason get source of the page and arrive at localhost/?onsubmit=productDefinition.runSearch() URL.
What can be the source of the problem and how can I get the same behaviour for onsubmit as for onclick?

#using (Html.BeginForm(new { onsubmit = "return runSearch();" }))
<script type="text/javascript">
function runSearch() {
// your logic to perform the search.
return true;
}
</script>

You need to use the following version of BeginForm method in order to specify html attributes.
However, it is considered a bad practice to use inline javascript so I would suggest to assign and id attribute to your form and handle its submit event in the external javascript file instead. If you are using jQuery for your project, here is a good example from their docs - http://api.jquery.com/submit/. In plan JavaSCript it is a bit more tricky but still easy to do.

#model Models.Person
<script type="text/javascript">
$(document).ready(function () {
$('#registerInputId').click(function () {
alert('what do you do before send? For example encrypt the password');
$('#Password').val(CryptoJS.MD5($('#Password').val()));
})
});
</script>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal" style="display: inline-block; margin: 5% auto;">
<div style="font-size: 18px; margin-right:2px; margin-bottom:20px; text-align:right;">Add form</div>
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-5" })
<div class="col-md-7">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Password, htmlAttributes: new { #class = "control-label col-md-5" })
<div class="col-md-7">
#Html.EditorFor(model => model.Password)
#Html.ValidationMessageFor(model => model.Password)
</div>
</div>
<div class="form-group" style="margin-top: 30px;">
<div class="col-md-offset-3 col-md-6">
<input id="registerInputId" type="submit" value="Register" class="btn btn-default" />
</div>
</div>
</div>
}

Form.Id is required if onsubmit handler implements generic functionality, applicable for multiple forms. (example : disabling all input fields)
Form
#using (Html.BeginForm(new {
id = "form24",
onsubmit = "return onSubmitHandler(id);"
}))
handler
<script type="text/javascript">
function onSubmitHandler(formId) { /*formId is form24 */ }
</script>

Related

Submitting a form from a partial view

I'm trying to submit a form from a modal generated in a partial view. And I don't know how to get back the submitted form.
Here is the view:
#model Myproject.ViewModels.GetMonitorFromDeviceViewModel
#{
ViewBag.Title = "GetMonitorFromDevice";
Layout = "~/Views/Shared/ManagementPage.cshtml";
}
<div id="Accordion">
#{
foreach (var type in Model.AvailableTypesAvailableMonitors)
{
<div class="card">
<div class="card-header">
<a class="card-link" data-toggle="collapse" data-parent="#accordion" href="##type">
#type
</a>
</div>
<div id="#type" class="collapse show">
<div class="card-body">
#{
foreach (var monitor in Model.ActiveMonitors)
{
if (monitor.Type == #type)
{
<p>
#monitor.Name
<span class="btn btn-xs btn-primary btnEdit" onclick="createModal('#Url.Action("NameMonitor", "DeviceManager" , new { idDevice = monitor.DeviceOwner.ID, monitorName = monitor.Name })')">Details</span>
</p>
}
}
}
</div>
</div>
</div>
}
}
</div>
And here is my modal at the bottom of the page:
<div class="modal fade" id="myModal" role="dialog" data-backdrop="static" data-keyboard="false">
<div class="modal-dialog">
<div class="modal-content" id="modelContent">
</div>
</div>
</div>
<script>
function createModal(url) {
$('#modelContent').load(url);
$('#myModal').modal('show');
}
</script>
And finally, here is my partial view that is displayed as a modal:
#model MyProject.ViewModels.NameMonitorModal
#using (Html.BeginForm("NameMonitor", "DeviceManager", FormMethod.Post))
{
<div class="modal-body">
<div class="form-group">
#Html.LabelFor(model => model.NewName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.NewName, new { htmlAttributes = new { #class = "form-control", #Value = Model.TrueName } })
#Html.ValidationMessageFor(model => model.NewName, "", new { #class = "text-danger" })
</div>
</div>
#Html.HiddenFor(model => model.TrueName)
#Html.HiddenFor(model => model.IdDevice)
</div>
<div class="modal-footer">
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save name" class="btn btn-default" data-dismiss="modal" />
</div>
</div>
</div>
}
In my controller, I have an action for my partial view called ActionResult NameMonitor.
In order to catch the submited form, I tried to add another action with the [HttpPost] tag with the same name but doesn't work. I also tried to use the main page action with the [HttpPost] tag but it doesn't work either. As you can see, I have specified the action and controller in the form itself but its still not working.
Now, I'm a little bit out of idea of how I can get the information from my modal back.
data-dismiss="modal" will close the modal without submitting the form, see Dismiss and submit form Bootstrap 3
You can change the submit button to call a JavaScript function to submit the form, then close the modal.
function submitModal() {
$('#myFormId').submit();
$('#myModal').modal('hide');
}

How to differentiate between selection and save in MVC post

I have a form which has a DropDownList to select users and a form for user data. All controls are nested inside a form.
Cureently user DropDownList submits the form to notify about user selection to fetch appropriate data.
I want have a Button type(submit) which saves the data for the current user. Since both controls are in the same form and they both do submit, how can I differentiate if I am trying to select the user or saving the data in my action?
I have tried creating two forms as follows:
#model MyApp.Models.UserModel
#{
ViewBag.Title = "Profiles";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script type="text/javascript" src="chosen.jquery.js"></script>
<script type="text/javascript" src="bootstrap-switch.js"></script>
<link rel="stylesheet" href="chosen.css" />
<link rel="stylesheet" href="bootstrap-switch.css" />
<style type="text/css">
.chosen-search{
display: none;
}
.form-group label{
margin-top: 10px;
}
.row{
margin-bottom: 20px;
}
th{
text-align: center;
}
</style>
<script type="text/javascript">
$(document).ready(function () {
$('#CurrentUserId').chosen({placeholder_text_single: "Select a user"});
$('#CurrentGroupId').chosen({placeholder_text_single: "Select a group"});
$('#CurrentRoleId').chosen({placeholder_text_single: "Select a role"});
$('#IsActive').bootstrapSwitch({
onColor: "success",
offColor: "danger",
onText: "ACTIVE",
offText: "PASSIVE",
animate: false,
handleWidth: 60
});
$('.authorizationCheckBox').bootstrapSwitch({
onColor: "success",
offColor: "danger",
onText: "Y",
offText: "N",
animate: false,
size: "mini"
});
});
</script>
#using (Html.BeginForm("Profile", "User"))
{
#Html.AntiForgeryToken()
<div class="row">
<div class="col-sm-3">
<div class="row">
<label class="control-label">Selected user :</label>
</div>
</div>
<div class="col-sm-9">
<div class="row">
#Html.DropDownListFor(x => x.CurrentUserId, new SelectList(Model.AllUsers, "Id", "Username"), "", new { #class = "form-control", onchange = #"this.form.submit();" })
</div>
</div>
</div>
}
#using (Html.BeginForm("SaveProfile", "User"))
{
if (!string.IsNullOrWhiteSpace(Model.CurrentUser))
{
<div class="row">
<div class="col-sm-3">
<div class="row">
#if (string.IsNullOrWhiteSpace(Model.UserImageUrl))
{
<img src="no-user.png" class="img-circle" alt="..." style="width: 35%; display: block; margin: auto;">
<button type="button" class="btn btn-primary" style="display: block; margin: auto; margin-top: 10px;">
<span class="glyphicon glyphicon-upload"></span> Upload avatar
</button>
}
else
{
<img src="#Model.UserImageUrl" class="img-circle" alt="..." style="width: 35%; display: block; margin: auto;">
<button type="button" class="btn btn-primary" style="display: block; margin: auto; margin-top: 10px;">
<span class="glyphicon glyphicon-retweet"></span> Change avatar
</button>
}
</div>
<div class="row">
<div class="input-group" style="margin: 0 auto;">
<div class="switch-button xlg showcase-switch-button">
#Html.CheckBoxFor(x => x.IsActive)
</div>
</div>
</div>
</div>
<div class="col-sm-9">
<div class="row">
<div class="form-group">
<label class="control-label col-sm-2">Username :</label>
<div class="col-sm-10">
<input id="CurrentUser" name="CurrentUser" class="form-control form-control-flat" value="#Model.CurrentUser" />
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<label class="control-label col-sm-2">E-mail :</label>
<div class="col-sm-10">
<input id="EMail" name="EMail" class="form-control form-control-flat" value="#Model.EMail" />
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<label class="control-label col-sm-2">Membership :</label>
<div class="col-sm-10">
#Html.DropDownListFor(x => x.CurrentGroupId, new SelectList(Model.AllGroups, "Id", "Name"), "", new { #class = "form-control" })
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<label class="control-label col-sm-2">Role :</label>
<div class="col-sm-10">
#Html.DropDownListFor(x => x.CurrentRoleId, new SelectList(Model.AllRoles, "Id", "Name"), "", new { #class = "form-control" })
</div>
</div>
</div>
</div>
</div>
<button id="btnSave" type="submit" class="btn btn-info" style="float: right; margin-right: 10px; margin-bottom: 40px;">
<span class="glyphicon glyphicon-trash"></span>Save changes
</button>
}
}
[HttpGet]
public ActionResult Profile()
{
return View(CreateInitialUserModel());
}
[HttpPost]
public ActionResult Profile(UserModel model)
{
model = GetUserModel(model.CurrentUserId.Value);
ModelState.Clear();
return View(model);
}
[HttpPost]
public ActionResult SaveProfile(UserModel model)
{
SaveModel(model)
return RedirectToAction("Profile");
}
But the problem is, at HttpPost of Profile action works well. But when I click the Save button and the HttpPost SaveProfile action is called, input parameter model does not have the values set on the screen.
I would actually use two forms. Not only does it relieve your problem here, as you can just add a hidden field or something to each form to indicate which was submitted, but it prevents other issues you're likely to run into, like failing validation on any required user fields in the create form, when you just select a user, because no data was submitted for those fields.
Short of that, just use whatever JavaScript you're already using to automatically submit when an option is selected from the drop down to change a value of a hidden field or otherwise modify the post data before it's submitted.
Why not use jquery for data retrieval? You could switch you dropdown to instead call a jquery function that performs an ajax call to a controller method that retrieves the relevant user data. Then, you can bind the data to the appropriate fields on the page using jquery. You would then only have one submit button on your view, handled through the normal mvc form process.
-in drop downdown list change event ,you should store UserID to a variable like global variable or hiddenfields.
-Create a Button
in function=
function submitvalues()
{
//get stored userID here from variable
//perform submit here
}

How To make own Template Inbox view use MVC using C#

I am using SMTP for mail sending . now its wokring normal mail message send to the inbox now i want own custom template with mail . i have using trying for simple layout own
#{
ViewBag.Title = "MyLayout";
}
<h2>MyLayout</h2>
in my contact us page
i have added this layout like this
#model Inspinia_MVC5.Models.MailModel
#{
ViewBag.Title = "Index";
#layout = "~/Views/Shared/MyLayout.cshtml";
}
<script src="~/Scripts/jquery-2.1.1.min.js"></script>
<script>
$(document).ready(function () {
$('.summernote').summernote();
if ('#ViewBag.Message' == 'Sent') {
alert('Mail has been sent successfully');
}
$(document).ready(function () {
$('.summernote').summernote();
});
});
</script>
<div class="wrapper wrapper-content">
<div class="row">
<div class="col-lg-2">
<div class="ibox float-e-margins">
<div class="ibox-content mailbox-content">
<div class="file-manager">
<div class="row">
<a class="btn btn-block btn-primary compose-mail" href="#Url.Action("ContactUs", "ContactUs")">Compose Mail</a>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-8 animated fadeInRight">
<div class="mail-box-header">
<h2>
Compse mail
</h2>
</div>
<div class="mail-box">
#using (#Html.BeginForm("ContactUs", "ContactUs", FormMethod.Post, new { #id = "form1", #enctype = "multipart/form-data" }))
{
<div class="mail-body">
<form class="form-horizontal" method="get">
<div class="form-group">
<label class="col-sm-2 control-label">To:</label>
<div class="col-sm-10"> <input type="text" name="To" class="form-control" placeholder="Enter your Email Here"></div>
</div>
<br />
<div class="form-group">
<label class="col-sm-2 control-label">Subject:</label>
<div class="col-sm-10"> <input type="text" name="Subject" class="form-control" placeholder="Enter Subject Here"></div>
</div>
<br/>
<br/>
<br />
#*#Html.TextBoxFor(m => m.Subject)*#
<div class="form-group">
<label class="col-sm-2 control-label">Attachment:</label>
<input type="file" name="fileUploader" />
</div>
</form>
<div class="mail-text h-200">
<div class="summernote">
#Html.TextAreaFor(m => m.Body, new { #class = "form-control", style = "width: 840px; height: 139px;" })
<br />
<br />
</div>
<div class="clearfix"></div>
</div>
<div class="mail-body text-right tooltip-demo">
#Html.ValidationSummary()
<input type="submit" class="btn btn-sm btn-primary" data-toggle="tooltip" data-placement="top" value="Send" />
</div>
</div>
}
</div>
</div>
</div>
</div>
#section Styles {
#Styles.Render("~/plugins/summernoteStyles")
#Scripts.Render("~/plugins/summernote")
}
after Running the code i am getting Error Like this
The layout page "= "~/Views/Shared/MyLayout.cshtml";" could not be found at the following path: "~/Views/ContactUs/= "~/Views/Shared/MyLayout.cshtml";"
please Any one tell how to send own template with mail to inbox
Should be:
#model Inspinia_MVC5.Models.MailModel
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/MyLayout.cshtml";
}

TagBuilder not generating unqiue id attribute values across ajax requests

I have an issue where I'm using the same template to render some content on a page and the same template is used to render additional content on the page using an AJAX request.
The following code renders the partial razor view:
#model SearchBoxViewModel
<div class="smart-search">
#using (Html.BeginForm("Index", "Search", FormMethod.Get, new { #class = "form-horizontal", role = "form" }))
{
<div class="form-group">
<div class="hidden-xs col-sm-1 col-md-1 col-lg-1 text-right">
#Html.LabelFor(m => m.SearchPhrase, new { #class = "control-label heading" })
</div>
<div class="col-xs-8 col-md-9 col-lg-10">
#Html.TextBoxFor(m => m.SearchPhrase, new {#class = "form-control", placeholder = "for products, companies, or therapy areas"})
</div>
<div class="col-xs-4 col-sm-3 col-md-2 col-lg-1">
<input type="submit" value="Search" class="btn btn-default"/>
</div>
<div class="what-to-search hidden-11 col-sm-11 col-sm-offset-1">
<div class="checkbox">
<label>
#Html.CheckBoxFor(m => m.WhatToSearch, null, false)
#Html.DisplayNameFor(m => m.WhatToSearch)
</label>
</div>
</div>
</div>
}
</div> <!-- /.smart-search -->
The following code makes the AJAX request:
$.ajax(anchor.attr("data-overlay-url-action"))
.done(function (data) {
$("div.overlay").addClass("old-overlay");
$("div.navbar").after(data);
$("div.overlay:not(.old-overlay)")
.attr("data-overlay-url-action", anchor.attr("data-overlay-url-action"))
.hide()
.fadeIn();
$("div.old-overlay")
.fadeOut()
.removeClass("old-overlay");
anchor.addClass("overlay-exists");
});
So what you get is the same partial razor view output on the page twice, once during the page request and once during the AJAX request.
The problem is that TextBoxFor, CheckBoxFor, etc. all make use of TagBuilder.GenerateId to generate the id attribute value but it doesn't account for generating id's across multiple requests where AJAX might be involved. This results in the same id value being output on the page, causing JavaScript to break.
The following is the HTML that is output twice (once during the request and then added in a separate part of the page during an AJAX request):
<div class="smart-search">
<form role="form" method="get" class="form-horizontal" action="/PharmaDotnet/ux/WebReport/Search"> <div class="form-group">
<div class="hidden-xs col-sm-1 col-md-1 col-lg-1 text-right">
<label for="SearchPhrase" class="control-label heading">Search</label>
</div>
<div class="col-xs-8 col-md-9 col-lg-10">
<input type="text" value="" placeholder="for products, companies, or therapy areas" name="SearchPhrase" id="SearchPhrase" class="form-control">
</div>
<div class="col-xs-4 col-sm-3 col-md-2 col-lg-1">
<input type="submit" class="btn btn-default" value="Search">
</div>
<div class="what-to-search hidden-11 col-sm-11 col-sm-offset-1">
<div class="checkbox">
<label>
<input type="checkbox" value="true" name="WhatToSearch" id="WhatToSearch">
NewsManager Search Only
</label>
</div>
</div>
</div>
</form></div>
So the SearchPhrase and WhatToSearch id's are duplicated.
Is there any way to work around this, or is there a better way to render the form elements to avoid this issue?
You could specify your own ID for the items, and then you wouldn't have this ID collision problem. Have you tried setting the id manually: Html.TextBoxFor( ... , new { id = "AnythingHere" }), where the id could be a freshly generated Guid? (Note that you'd probably need to add a prefix, because Guids can start with a number.
So you can use the following. The Guid doesn't look good, and is unnecessarily long. You might want to go with something shorter, like short guid, DateTime.Ticks, ...
#{
var id = "chk_" + Guid.NewGuid().ToString();
}
#Html.CheckBoxFor(..., new { id = id })
#Html.LabelFor(..., new { #for = id })

ASP MVC Submit button not doing anything. At all

I have a (simple) ASP MVC view:
<div class="row">
<div id="dashboard-left" class="col-md-8">
#using (Html.BeginForm("ConfigureOffers", "Offers", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div style="padding-bottom: 10px;">
<p style="font-size: large;"><strong>Available</strong></p>
</div>
<div class="accordion" id="accordion2">
<div class="widget" style="background:#fff !important">
#{
int i = 0;
}
#foreach (var prod in Model.allProducts)
{
<div class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" data-parent="accordion2" href="#collapse#(i)">
<h4 class="widgettitle" id="QuickTitle">> #prod.Description_VC</h4>
</a>
</div>
<div id="collapse#(i)" class="accordion-body collapse" style="height: 0px;">
<div class="accordion-inner" style="margin-left: 10px;">
<div style="padding-bottom: 10px;"><strong>Total product:</strong> #{
for (int k = 0; k < Model.OfferHeaders.Count(); k++)
{
if (Model.OfferHeaders[k].Product_ID == prod.Product_ID)
{
#Html.TextBoxFor(o => o.OfferHeaders[k].Amount_DEC);
break;
}
}
}
</div> #*prod div*#
</div> #*accordion-inner*#
#{i++;}
</div>
<div style="clear:both;"></div>
</div>
}
<input type="submit" class="btn btn-default" value="Save Changes" />
</div> #*widget*#
</div> #*accordion*#
}
</div>
<!-- col-md-4 -->
</div>
<!--row-->
The basis of this view was taken from another (working page), but for some reason, clicking the submit button doesn't trigger the server action detailed in the BeginForm element. I get no errors from Visual Studio, nor any JavaScript errors from the browser console, and nothing seems to happen server-side.
One possible reason for Action not happening is mainly when you put
the action in the View and also created the page. but i think you
have forgot mentioning the ActionResult in the controller.
Another possible option is you have to use [HttpPost] above your
method in controller where you specified the ActionResult
[HttpPost]
public ActionResult ConfigureOffers(ModelClass instance)
{
...
}
Other possible reasons
The routes are not correct
The Form Action property is not correct
You are using nested FORM tags

Categories