MVC Partial Page Submit from JQuery UI Dialog - javascript

I am trying to submit an ajax form that is loaded via a partial page. The submit comes from a button that is created on a JQuery UI Dialog. The form data is included in the request but when I step through the code on the server side the view model is not being populated with the data.
Javascript that loads the partial and after load is complete creates the dialog.
$('#test').load('#Url.Action("NewIntegrationLevel", "IntegrationLevelConfig", null, Request.Url.Scheme)',
function() {
var dialog = $('#addEditForm');
dialog.dialog({
resizable: false,
modal: true,
width: 500,
title: 'New Integration Level',
buttons: [{
text: 'Save',
click: function(e) {
e.preventDefault();
$('#addEditForm').submit();
dialog.dialog('close');
},
type: 'submit',
form: 'addEditForm'
},
{
text: 'Close',
click: function(e) {
e.preventDefault();
dialog.dialog('close');
}
}
]
});
});
My partial page:
#model Zodiac.Cmt.UI.Models.IntegrationLevelConfigViewModel
#using (Ajax.BeginForm("Save", "IntegrationLevelConfig", FormMethod.Post, null, new { id = "addEditForm" }))
{
<div id="addEdit-integration-dialog">
<div>
<div>
#Html.LabelFor(model => model.Name)
#Html.TextBoxFor(model => model.Name)
</div>
</div>
</div>
}
Server side code:
[HttpPost]
public ActionResult Save(IntegrationLevelConfigViewModel viewModel)
{
return PartialView("_AddEditIpl", viewModel);
}
Since the JQuery dialog creates the submit button outside the form I am using the "form" attribute on the button so that it knows which form to submit.
This is what the request looks like after submitting the page:
So, why doesn't the viewmodel get populated with the form data on the server side???
ViewModel:
public class IntegrationLevelConfigViewModel
{
[Description("Name")]
public string Name;
}

I figured it out.
In my view model
public string Name;
needs to change to:
public string Name {get;set;}

Related

Validate username and password without postback in login form ASP.NET MVC

I want to validate the entered username and password entered in the textboxes present in a form without Postback/Refresh. I know I am gonna need Javascript or AJAX for this purpose, but somebody please guide me through this like refer me to any tutorial or please explain me the code here.
My present code without this feature looks like this:
#using(Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.TextBoxFor(u => u.PPNumber, new { #class = "form-control", type = "number", placeholder = "Enter Number",#min="1" })
#Html.ValidationMessageFor(u => u.PPNumber)
#Html.TextBoxFor(u => u.Password, new { #class = "form-control", type = "Password", placeholder = "Password" })
#Html.ValidationMessageFor(u => u.Password)
<input type="submit" value="Login" class="btn btn-primary btn-block" />
}
You can use ajax.
When user submits the form, you need to hijack that event in javascript and stop that(prevent the normal full page form submit) and instead make an ajax call to the action method with the form data. This action method should have code to verify the user credentials and can return a JSON data structure which has a status property which says whether the credential validation is successful or not. You can inspect this response in your ajax call's success/done callback and act accordingly.
Here is a quick sample using jQuery $.post method.
Give an Id to your form so that we can use that to wire up the submit event.
#using (Html.BeginForm("Login", "Account", FormMethod.Post, new { id="loginForm"))
{
#Html.TextBoxFor(u => u.PPNumber)
#Html.TextBoxFor(u => u.Password, new { #class = "form-control", type = "Password"})
<input type="submit" value="Login" class="btn btn-primary btn-block" />
}
and the javascript code to hijack the submit event and do an ajax post instead.
$(function () {
$("#loginForm").submit(function(e) {
e.preventDefault();
$.post($(this).attr("action"), $(this).serialize())
.done(function(response) {
if (response.status === 'success') {
alert("Login successful.Do something else now");
} else {
alert("Login failed");
}
});
});
});
Assuming your Login action method in AccountController will return a Json response with a status property.
public ActionResult Login(string PPNumber,string password)
{
if(PPNumber=="thisIsDemo" && password=="ButDoTheActualCheck")
{
return Json(new { status = "success" });
}
return Json(new { status = "failed" });
}
Here i just hard coded the usrename /password check to 2 static values. You can change that to check it against your db table/whatever your credentials checking mechanism is.

Javascript button click causing multiple Post

I have the following script which is rendering a partial view inside a dialog box:
$(function () {
$('#addressLookupBtn').click(function () {
$('#dialog').dialog({
title: 'Address Lookup Tool',
modal: true,
width: '1200',
height: 'auto',
resizable: false,
show: {
effect: "fade",
duration: 2000
},
hide: {
effect: "fade",
duration: 1000
},
open: function (event, ui) {
//Load the AddressLookup action which will return
//the partial view: _AddressLookup
$(this).load("#Url.Action("AddressLookup", new { evpId = Model.EvpId })");
}
}).dialog('open');
});
});
The problem is, when I submit the partial view, there are 2 POSTS being made to the server, I think the submit for the partial view is also being bound to the $('#addressLookupBtn').click. Can anyone see where I'm going wrong?
more info
Partial view
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "updatearea" }))
{
<div id="updatearea" class="form-group">
<div style="width:300px; display:block; float:left;">
#Html.TextBox("PostCode", null, new { #class = "form-control" })
</div>
<div id="NewAddressLine">
<input type="submit" value="Lookup Postcode" class="btn btn-default" />
</div>
</div>
}
It looks like the post is being submitted using both a normal form submit and as a jquery event.
Perhaps change it to a button (instead of submit) and use only the jquery submit, or remove the jquery event and use only the normal form submit.
As per comments - An example of using jquery ajax instead of MS ajax:
The script:
$(document).ready(function() {
event.preventDefault(); // stop the form from submitting the normal way
$('#MyForm').submit(function(event) {
$.post(
$('#MyForm').attr('action'),
{ 'PostCode' : $('input[name=PostCode]').val() }
)
.done(function(data) {
alert('Post worked, and data was returned. Parse and/or present.');
$('#updatearea').html(data); //Replace the current contents of "updatearea" with the returned contents
});
});
});
The PartialView:
#using (Html.BeginForm("MyAction", "MyController", new { #id = "MyForm" }))
{
<div id="updatearea" class="form-group">
<div style="width:300px; display:block; float:left;">
#Html.TextBox("PostCode", null, new { #class = "form-control" })
</div>
<div id="NewAddressLine">
<input type="submit" value="Lookup Postcode" class="btn btn-default" />
</div>
</div>
}
It looks like you are calling open, and still have autoOpen set to true (it is true by default). This is causing open event to run twice. Try setting autoOpen to false
$('#dialog').dialog({
...
autoOpen: false,
...
});
https://api.jqueryui.com/dialog/#option-autoOpen
It turns out I didn't need to change anything other than move the following bundle reference from _Layout to my Edit view:
#Scripts.Render("~/bundles/unobtrusive-ajax")

Why is Form in Partial view not being validated by jquery?

I'm gonna try to keep the code to a minimum here.
In my MVC3 application using c# I have a form in a partial view and the submit button in the main view. I have the [required] attribute on the model properties used in the partial view and also rules set out in an associated javascript file.
But when a user a doesn't enter any data on the field in the form no validation is executed and the application continues.
I assumed the following steps would be correct.
I have the Javascript file referenced in the main view.
The form Id is referenced in this javascript file as is the input id of the submit input form the main view.
Example of model property:
[Required]
[ScaffoldColumn(true)]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
[DataType(DataType.Date)]
[Display(Name = "Expected Return Date to Customer")]
public DateTime? ExpectedReturnedToCustomer { get; set; }
Form tag in partial view:
<form id="multipleenroutetoltslab" method="post"
Partial view is called via #{Html.RenderPartial();}
Input tag used for Submit.
<input type="submit" style="width:100%;" class="styledbutton" id="MultiSubBtn" value="Submit" />
Javascript file reference in main view (part of a bundle):
.Add("~/Scripts/CalibrationViewer/MultipleEnRouteToLtsLab.js")
Javascript file :
$(document).ready(function () {
$('#MultiSubBtn').click(function () {
$('#multipleenroutetoltslab').validate({
errorClass: 'field-validation-error',
errorPlacement: function (error, element) { //place the error method after the date picker component
var trigger = element.next('.ui-datepicker-trigger');
error.insertAfter(trigger.length > 0 ? trigger : element);
},
rules: {
SentBy: {
required: true,
maxlength: 255
},
DateSentToLtsLab: {
required: true,
dateFormat: true
},
ExpectedReturnedToCustomer: {
required: true,
dateFormat: true
}
},
The view Partial View:
#model EnRouteToLts_RecByLts
<form id="multipleenroutetoltslab" method="post">
<p>
#Html.LabelFor(m => m.SentBy)
#Html.TextBoxFor(M => M.SentBy, new { disabled = "disabled", #readonly = "readonly" })
</p>
<p>
#Html.LabelFor(m => m.DateSentToLtsLab)
#Html.TextBox("DateSentToLtsLab", Model.DateSentToLtsLab.HasValue ? Model.DateSentToLtsLab.Value.ToShortDateString() : DateTime.Now.ToShortDateString(), new { disabled = "disabled", #readonly = "readonly" })
</p>
<p>
#Html.LabelFor(m => m.ExpectedReturnedToCustomer)
#Html.TextBox("ExpectedReturnedToCustomer", Model.ExpectedReturnedToCustomer.HasValue ? Model.ExpectedReturnedToCustomer.Value.ToShortDateString() : null, new { #class = "date-picker" })
</p>
</form>
There is more code the javascript file if needed.
I placed an alert after the $('#MultiSubBtn').click(function () { and it was fired so the file is being reached but rules are not being applied.
Also it should be noted when data is entered in the form it does reach the Post action.
No errors.

How to enable/disable save button of backbone form-view when user changes form content

I have form which gets data from backbone model. When the form is shown, they have initially value set to backbone model. Now, if any field is edited, i want to enable "save" button immediately as soon as any changes is made to field. However, if you change field value and again change it to original, it should again disable the "save" button that allows to save model.I want to achieve as one shown in this jsfiddle :http://jsfiddle.net/qaf4M/2/
I am using backbone.js and backbone.stick (http://nytimes.github.io/backbone.stickit/) to bind model to template.
I create view as follows with model as parameter
RegionManager.show(new app.myView({
model : new app.myModel(
{id: 1})
}));
MY model value is something like this:
{
"id":1, "name:"a" , "age":21
}
The view is as follows:
myView = Backbone.View.extend({
template: _.template( $("#template").html() ),
events: {
"click #save" : "update",
},
bindings: {
'#id': 'id',
'#name': 'name',
'#age': 'age'
},
initialize: function () {
if(this.model){
this.model.fetch();
},
render: function () {
this.$el.html( this.template );
this.stickit(); //used library http://nytimes.github.io/backbone.stickit/
Backbone.Validation.bind(this);
},
update: function() {
this.model.save (
{success: this.success_callback, error: this.error_callback});
},
success_callback: function (model, response) {
},
error_callback: function (model, response) {
alert('error.');
}
});
My template look like
<script type="text/template" id="template">
<form id="myForm " >
<fieldset>
<label>Name</label>
<input type="text" id="name" name="name" />
<label>Age</label>
<input type="text" id="age" name="age" />
<input type="hidden" id="id" name="id"/>
</fieldset>
<a id="save" disabled >Save Changes</a>
</form>
I am confused where should i bind event and how or what is proper way to know the user has chagne some value and accordingly disable button when there is no cahnge in form and enable when change has been made.
A simple solution would be to make your view listen to your model's changes:
initialize: function () {
if(this.model){
this.model.fetch({
success: function(model, resp) {
this.model._attributes = resp; // create a copy of the original attributes
this.listenTo(this.model, 'change', function() {
// when the model changes
// maybe write some function to compare both
if(_.isEqual(this.model._attributes, this.model.toJSON())) {
// disable
}
else {
// able
}
});
}
});
}
So, when the data comes back from the server, you create a copy, and then listen to your model's changes. If the new attributes equal the original, disable the button.

Unable to overload submit method of Ajax.BeginForm

I'm trying to submit an ajax form from my razor view, and I want the controller to return a JSON object. When I use ("#form0").submit(alert("hi");); the data goes to the controller and I get an alert. However, when I use ("#form0").submit(function(){alert("hi");}); the data does not get passed, and I do not get an alert. I get the feeling that this is something minor with my syntax that I'm missing. Here's the relevant code:
jquery:
$(function () {
//setting up the schedule modal dialoag.
$("#schedModal").dialog({
buttons: {
Submit:
function () {
$("#form0").ajaxSubmit(function () {
//this is where I want to put the magic, but I need the alert to fire first.
alert("hi");
return false;
});
},
Cancel:
function () {
$(this).dialog("close");
}
},
autoOpen: false,
minHeight: 350,
modal: true,
resizable: false
});
the targeted view:
#model FSDS.DataModels.Schedule
#using (Ajax.BeginForm("scheduleNew", null, new AjaxOptions { UpdateTargetId = "partial" }, new {}))
{
#Html.ValidationSummary(true)
<div class="editor-label">
#Html.LabelFor(model => model.ScheduleName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ScheduleName)
#Html.ValidationMessageFor(model => model.ScheduleName)
</div>
#* tons of other labels and editor fields go in here, omitted for brevity. *#
}
The controller, if that matters:
[HttpPost]
public ActionResult scheduleNew(Schedule schedule)
{
if (Request.HttpMethod == "POST")
{
FSDSDBEntities context = new FSDSDBEntities();
if (ModelState.IsValid)
{
context.Schedules.AddObject(schedule);
context.SaveChanges();
}
return Json(schedule);
}
else
{
return PartialView();
}
}
Simply use $('#form0').submit();:
Submit: function () {
$('#form0').submit();
}
Then define an OnSuccess handler in your AjaxForm that will be invoked when the AJAX request succeeds:
#using (Ajax.BeginForm("scheduleNew", null, new AjaxOptions { OnSuccess = "success", UpdateTargetId = "partial" }, new {}))
and finally success javascript handler:
function success(data) {
// the form was successfully submitted using an AJAX call.
// here you could test whether the data parameter
// represents a JSON object or a partial view
if (data.ScheduleName) {
// the controller action returned the schedule JSON object
// => act accordingly
} else {
// the controller action returned a partial view
// => act accordingly
}
}

Categories