MVC3, Ajax and a modal form with client-side unobtrusive validation - asp.net-mvc-3

I can't get the combination of things in the title to work together. I've read various questions but not found one that covers everything I'm trying to do.
I'm using jqModal for my modal window. I'm using Ajax.BeginForm. My models are decorated with [Required], [Display(...)] etc.
This stuff is all being placed on a page using #Html.RenderAction(...)
Depending on whether I use OnBegin or OnComplete in the ajax call, I either get no client-side validation (the update just doesn't take), or the modal gets stuck in a state where the whole page is "modalled out" without a dialog in place. But actually what I want is for the modal to stay in place if there is either a client or server side validation error.
The site does not require any functionality to work without javascript being available/enabled.
head:
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/jquery.cleditor.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/jqModal.css")" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery-1.6.1.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.validate.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.cleditor.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/jquery.timeago.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/jqModal.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Scripts/functions.js")"></script>
The model:
public class ReplacedTextModel {
public ReplacedTextModel() { }
public ReplacedTextModel(int id, string text, string replaced) {
Id = id;
Text = text;
Replaced = replaced;
}
public int Id { get; set; }
[Required, Display(Description = "The text of the question", Prompt = "Please enter the question text."), UIHint("MultilineString")]
public string Text { get; set; }
public string Replaced { get; set; }
}
The editor template (this contains some extension methods but they're not relevant to the problem, so please ignore):
#model string
<div class="form-element">
#Html.Label("", new Dictionary<string, object> { { "title", Html.Description("") } })
#if (Html.IsRequired()) {
<span class="form-required">*</span>
}
<div class="form-control">
#Html.TextArea("", Model, new Dictionary<string, object> { { "title", Html.Prompt("") } })
<div class="form-validation">
#Html.ValidationMessage("")
</div>
</div>
</div>
The view (there may be many of these on a page, and they may be repeated, so I'm using the Guids for uniqueness):
#model ReplacedTextModel
#{
var id = Guid.NewGuid().ToString("N");
var windowId = "id_" + id + "_window";
var triggerId = "id_" + id + "_trigger";
var replaceId = "id_" + id + "_replace";
var functionId = "id_" + id + "_closeForm";
}
<div id="#replaceId">
#Html.Raw(Model.Replaced)
<span class="edit-mode"><a id="#triggerId" href="#">edit</a></span>
<div id="#windowId" class="jqmWindow" style="display: none">
#using (Ajax.BeginForm("Text", new AjaxOptions { UpdateTargetId = replaceId, OnBegin = functionId, HttpMethod = "POST" })) {
#Html.HiddenFor(x => x.Id)
#Html.EditorFor(x => x.Text)
<input type="submit" value="Save" />
}
<div>Cancel</div>
</div>
<script type="text/javascript">
$(function () { $("##windowId").jqm({ trigger: "##triggerId" }); });
function #(functionId)() {
// THIS IS A PROBLEM
// if it's not called or is called on OnBegin then the modal doesn't close properly
// if OnComplete is used, the dialog disappears but the validation doesn't work
// in either case, validation failure on backend (try posting whitespace) doesn't show validation errors.
$("##windowId").jqmHide();
};
</script>
</div>
The controller methods:
public ActionResult Text(int id) {
return PartialView("Text", ReplacedTextModel.Get(id));
}
[HttpPost]
public ActionResult Text(int id, string text) {
if (ModelState.IsValid) {
try {
if (string.IsNullOrWhiteSpace(text)) throw new ArgumentException("No text was provided for the question.", "text");
ReplacedTextModel.Update(id, text);
} catch (Exception ex) {
ModelState.AddModelError(ex);
}
}
return Text(id);
}
Sorry for the long post, but I've seen others mention that it's not a bad thing! Happy to post any additional code/info if requested. I may have missed something as I have copy/pasted from a few locations in the project.
Thanks in advance.

Related

How to refresh PartialView by calling ActionLink in Grid in PartialView

I have a PartialView, that contains grid. The grid has a list of files that can be deleted. After user deletes the file I return PartialView with new file list.
Issue:
The new screen contains ONLY the PartialView. The MenuItems and all other things on the page are NOT rendered.
Any help highly appreciated. Thank you...
MY code:
Sellers.cshtml
'ACSDemoWinAzureACS.Models.SellersModel
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-2.1.0.min.js")" type="text/javascript"></script>
<script src="../../Scripts/jquery-ui-1.8.20.js" type="text/javascript"></script>
<script src="../../Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script>
<div id="gridContainer">
#Html.Partial("_AdminView", Model)
</div>
'
_AdminView.cshtml - The PartialView
#model ACSDemoWinAzureACS.Models.HomeModel
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-2.1.0.min.js")" type="text/javascript"></script>
<script src="../../Scripts/jquery-ui-1.8.20.js" type="text/javascript"></script>
<script src="../../Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script>
<div id="gridMain">
#using (Html.BeginForm("Admin", "Home", new { enctype = "multipart/form-data" }))
{
foreach(var file in Model.files)
{
<tr>
<td> #file.FileName</td>
<td>#Ajax.ActionLink("Delete" , "Delete" , "Home",
new { id = file.FileName },
new AjaxOptions
{
UpdateTargetId="gridMain", // <-- DOM element ID to update
InsertionMode = InsertionMode.Replace, // <-- Replace the content of DOM element
HttpMethod = "GET" // <-- HTTP method
})
</td>
</tr>
}
}
</div>
HOmeController.cs
public PartialViewResult Delete(string id)
{
_model.Delete(id);
_model.files = _model.GetFiles();
return PartialView("_AdminView",_model);
}

jQuery multiple tabs + validation select does not fire (MVC3/Razor/VB)

I've used a solution here (which I've fiddled here) for restricting submission of a form until all required fields are filled.
The problem is when I run on my MVC3 project, as I've observed on Firebug, it stops starting at the third line of the following block. Because of it, the solution doesn't work.
var validator = $("#myForm").validate();
var tabs = $("#tabs").tabs({
select: function(event, ui) { // Here.
// The following lines are not executed.
var valid = true;
var current = $(this).tabs("option", "selected");
var panelId = $("#tabs ul a").eq(current).attr("href");
Can somebody tell me why my project won't run the rest of the script and what I should do to fix it? Thanks!
In my View file
#ModelType SLC.Models.RegisterModel
// downloaded with NuGet
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
var validator = $("#myForm").validate();
console.log(validator);
var tabs = $("#tabs").tabs({
select: function (event, ui) {
var valid = false;
var current = $(this).tabs("option", "selected");
var panelId = $("#tabs ul a").eq(current).attr("href");
$(panelId).find("input").each(function () {
console.log(valid);
if (!validator.element(this) && valid) {
valid = false;
}
});
return valid;
}
});
});
</script>
<link rel="stylesheet" href="#Url.Content("~/Content/themes/base/jquery-ui.css")" />
#Using Html.BeginForm("", "", Nothing, New With {.id = "myForm"})
#Html.ValidationSummary(True, "Account creation was unsuccessful. Please correct the errors and try again.")
#<div>
<div id="tabs">
<ul>
<li>1. Information</li>
<li>2. Information</li>
<li>3. Confirm</li>
</ul>
<div id="tab-1">
// Some fields...
</div>
<div id="tab-2">
// Some fields...
</div>
<div id="tab-3">
// Some fields...
<input type="submit" value="Register" />
</div>
</div>
</div>
End Using
In my Layout template file
<head>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
// downloaded with NuGet
<script src="#Url.Content("~/Scripts/jquery-1.9.1.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery-ui-1.10.0.js")" type="text/javascript"></script>
</head>
I found this:
The jQuery UI select method, in particular, is deprecated as of 1.10.0, so it's either back to UI 1.9.2 or a code rewrite.

ajax-jquery not working for Spring MVC on change event of select

I am new to spring MVC. I want my jsp page to use ajax to populate a select box on the change event of another select box..
the jsp page is like..
<c:url var="RatePlanOfClientURL" value="/ratePlansofUser.jav" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<link rel="stylesheet" href="Scripts/jquery-ui-1.8.16/themes/base/jquery-ui.css" type="text/css" />
<link rel="stylesheet" href="Scripts/jquery-ui-1.8.16/themes/base/jquery.ui.autocomplete.css" type="text/css" />
<script src="Scripts/jquery-ui-1.8.16/jquery-1.6.2.js"></script>
<script type="text/javascript" src="Scripts/jquery-ui-1.8.16/ui/jquery-ui.js"></script>
<script type="text/javascript" src="Scripts/jquery-ui-1.8.16/ui/jquery.ui.core.js"></script>
<script type="text/javascript" src="Scripts/jquery-ui-1.8.16/ui/jquery.ui.position.js"></script>
<script type="text/javascript" src="Scripts/jquery-ui-1.8.16/ui/jquery.ui.widget.js"></script>
<script type="text/javascript">
window.scrollTo(0, 1);
</script>
<script type="text/javascript">
$(document).ready(function() {
$("#parentClient").change(function(){
$.getJSON('${RatePlanOfClientURL}', {
clientId : $(this).val(),
ajax : 'true'
},
function(data) {
alert("hai");
var html = '<option value="">Select '+$("#parentClient").val()+'</option>';
var len = data.length;
for ( var i = 0; i < len; i++) {
html += '<option value="' + data[i].rateID + '">' + data[i].rateName
+ '</option>';
}
html += '</option>';
$('#ratePlanList').html(html);
});
});
});
</script>
<fieldset>
<div>
<label> Parent Account</label>
<form:select id="parentClient" path="reseller.clientResellerParentId" class="addDropdown">
<form:option value="0" label="Select Parent"></form:option>
<form:options items="${ClientList}" itemValue="clientId" itemLabel="clientName"/>
</form:select>
</div>
<div>
<label >Rate Plan</label>
<form:select id="ratePlanList" path="reseller.resellerRateplan.ratePlanID" class="addDropdown">
<form:option value="0" label="Select RatePlan"></form:option>
<form:options items="${RatePlanList}" itemValue="rateID" itemLabel="rateName"/>
</form:select>
<form:errors path="reseller.resellerRateplan.ratePlanID" cssStyle="color:red"></form:errors>
</div>
</fieldset>
And in my controller class
#RequestMapping(value = "/ratePlansofUser.jav", method = RequestMethod.GET)
public #ResponseBody List<RatePlanData> ratePlansForClient(
#RequestParam(value = "clientId", required = true) Integer clientId,
HttpSession session)
{
System.out.println("Reached Controller for "+clientId);
return ratePlanService.getRatePlanForClient(clientId);
}
Atlast the database controller class i have
public List<RatePlanData> getRatePlanForClient(int id)
{
Criteria myCriteria = sessionfactory.getCurrentSession().createCriteria(RatePlanData.class);
myCriteria.add(Restrictions.eq("clientID",id ));
return myCriteria.list();
}
Whenever i change my parentclient select box, the controller method is calling( the System.out.println("Reached Controller for "+clientId); is printing). And when i select a parent which doesnt have any child, the alert box in that script is displaying. But when i call a parent which has child, it is not working(that alert box is not displaying, but that System.out.println("Reached Controller for "+clientId); is printing at console).
Can anyone point out what may the problem?
Thanks in advance..
Edit..
I had checked the variable data in the ajax function in script with firebug. it shows the value for data as '[ ]' when i am selecting a parent which has no child. And it just skips all the scripts when it encounters the function(data). Does anyone got any idea??
First of all, you need to make sure that your service call doesn't throw any exception. Secondly if there is no exception, you might be missing the Id / element name generated by spring tag (assuming you are using spring tag lib)

Data posted from Html editor not works in Chrome

I am using Html Editor in MVC3 view to store article info as:
#using (Html.BeginForm())
{
...
#Html.TextAreaFor(model => model.OtherInformation, new { #id = "OtherInformation" })
...
}
<link href="#Url.Content("~/Content/jquery.cleditor.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery.cleditor.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.cleditor.xhtml.min.js")" type="text/javascript"></script>
<script type="text/javascript">
$("#OtherInformation").cleditor();
</script>
and in controller I have written the code to save article as:
[ValidateInput(false)]
[HttpPost]
public ActionResult Create(Article article)
{
if (ModelState.IsValid)
{
article.EntryDate = DateTime.Now;
new ArticleService().SaveOrUpdateArticle(article);
return RedirectToAction("ArticleIndex");
}
return View(article);
}
This all works fine in IE,but when I run the same in Chrome then "OtherInformation" always go Null.
This problem was fixed in version 1.4.0.

C# Variable To JavaScript

<index>
<div>
string selectedvalue="";
// Coding Part
</div>
<script type="text/javascript">
function onchangeFT(e)
{
'#selectedvalue'= e.value; //e.value come form combobox and it is should be assigned to "selectedvalue"
alert('#selectedvalue');
}
</script>
<script type="text/javascript">
var selectedvalue="";
function onchangeFT(e)
{
selectedvalue = e.value; //e.value come form combobox and it is should be assigned to
alert(selectedvalue);
}
</script>

Resources