jQuery .blur method not working - asp.net-mvc

I am trying to set up an Ajax call whenever the user enters information into a particular field on my ASP MVC web page. Below is the jQuery .blur method
$('#MailingZip').blur(function () {
alert("here");
if ($('#MailingState').val() != "" && $('#div.channelName').text() != "") {
alert("inside Mailing Zip");
getDrmTerritory($('#MailingZip').val(), $('#MailingState').val(), $('#div.channelName').text());
}
});
and here is the control from the view.
<div class="M-editor-label">
#Html.LabelFor(model => model.MailingZip)<span class="req">*</span>
</div>
<div class="M-editor-field">
#Html.TextBoxFor(model => model.MailingZip, new { maxlength = 15, onchange = "CheckTerritory('M');" })
#Html.ValidationMessageFor(model => model.MailingZip)
</div>
I just started w/jQuery a couple weeks ago, so I'm not sure what's wrong. FYI, none of the alerts are working and if I set a breakpoint at the first if statement it doesn't fire.

Make sure you put your code inside of the $(document).ready() function, this ensures that the DOM is fully loaded before you manipulate any of its contents:-
$(document).ready(function() {
// your code here!
});

Related

Disabled property not working for ListBoxFor and DropDownListFor

I have a web page that dynamically creates components by rendering them through a RenderPartial Html Helper like this
Html.RenderPartial("_UploadStaticField", config);
Within the config object is a field called 'isUnderReview'. When this is set to true the components should be disabled by using the code below
//Single selection
<div class="editor-section">
<div class="label">
#Html.DisplayEditLabel(Model.Label, Model.Required.Value)
</div>
<div class="field large-text-field">
#Html.DropDownListFor(m => m.SelectedListOptionID, new SelectList(Model.ListOptions, "ID", "Name", Model.SelectedListOptionID).OrderBy(l => l.Value), new Dictionary<string, object>{
{"id", "staticField_" + Model.ID}})
</div>
</div>
<script>
$(document).ready(function () {
if ("#Model.IsUnderReview" == "True") {
document.getElementById("staticField_" + "#Model.ID").disabled = true;
}
});
</script>
and..
//Multiple selection
<div class="editor-section">
<div class="label">
#Html.DisplayEditLabel(Model.Label, Model.Required.Value)
</div>
<div class="field large-text-field">
#Html.ListBoxFor(x => x.SelectedRoles, filetypes, new { #class = "multiselectFileTypes" , id = "staticFieldM_" + Model.ID})
</div>
</div>
#Scripts.Render(BundleConfig.Scripts_MultiSelect)
<script>
$(document).ready(function () {
if ("#Model.IsUnderReview" == "True") {
document.getElementById("staticFieldM_" + "#Model.ID").disabled = true;
}
});
</script>
The code works to the point that the methods run but the components are still able to be used. Is there a way of cancelling any users selections which will serve as disabling as the values wont change?
Scripts should never be in partials (you potentially generating multiple inline scripts that may cause other problems, especially with the bundle). However a script is not even necessary for this, you can use a simple if statement or conditional attributes to generate what you want.
When you say "but the components are still able to be used", I'm guessing that your using a plugin to generate controls as suggested by Scripts.Render(BundleConfig.Scripts_MultiSelect) which will be hiding the original <select> element and generating its own html which is why it still interactive.
But the next problem is that disabled controls do not post back a value, so the vales of SelectedListOptionID and SelectedRoles will be their default, possibly resulting in your app failing depending on the code in your POST method.
Move the #Scripts.Render() into you view or layout, delete the scripts to disable the element and then change the partial to
#if(Model.IsUnderReview)
{
#Html.HiddenFor(m => m.SelectedListOptionID) // if you want the value to be posted
// add an element to display the Name associated with the SelectedListOptionID
// if necessary, for example your view model might include a property
// string SelectedListOptionName
}
else
{
#Html.DropDownListFor(m => m.SelectedListOptionID, new SelectList(Model.ListOptions, "ID", "Name").OrderBy(l => l.Value))
}
Side notes:
There is no reason to add you own id attribute (the
DropDownListFor() method generates <select
id="SelectedListOptionID" ... >
Remove the last parameter of the SelectList constructor
(Model.SelectedListOptionID) - its ignored by the
DropDownListFor() method. I also recommend your model contains an IEnumerable<SelectListItem> OptionsList property and you populate that in the controller so that it can simply be #Html.DropDownListFor(m => m.SelectedListOptionID, Model.OptionsList)

JQuery AJAX: Update ViewModel

I have a strongly-typed MVC view that includes a form with an editor that is bound to a view model:
#model ViewModels.CommentView
#using (Ajax.BeginForm("UpdateComments", new AjaxOptions { HttpMethod="POST" }))
{
<fieldset>
<legend>Metadata</legend>
<div>
#Html.HiddenFor(model => model.Id)
<div class="editor-label">
#Html.LabelFor(model => model.Comment)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Comment)
#Html.ValidationMessageFor(model => model.Comment)
</div>
</div>
<p class="action clear">
<input type="submit" value="Save" />
</p>
</fieldset>
}
When the user clicks on an element in a different part of the view, a JQuery AJAX call retrieves data from the server and updates the control:
<script type="text/javascript">
$(".load-comments").focus(function () {
var Id = $("#Id").val();
var url = "#Url.Action("GetComment")/" + Id;
$.ajax({ url: url, success: DataRetrieved, type: 'POST', dataType: 'json' });
function DataRetrieved(data) {
if (data) {
$("#Comment").val(data.Comment);
}
};
});
</script>
This functionality works as expected: the control content is visually updated. However, the value of the underlying html element is not updated, and when I post the form back to the server, the view model is empty.
How do I set the form controls' value in the JQuery function so that they post back to the server?
How did you set the HTML? ASP.NET default ModelBinder looks for id that are equals object properties to build the model back in the server. Looks like your form HTML doesnot reflect the object. Inspect each element created by Html helper and create each control as the same after comment data comes from the request. Hopes its help you! You can create a custom ModelBinder to Bind your model back in the server, take a look here: Model Biding

javascript validate not working in mvc app

In my MVC4 app, I'm trying to create a client side validator for some textboxes in a form. The form is contained in the Register.cshtml view (this view is automatically created by VS2010 when i make a new MVC4 with formsauthentication project).
The form already implements validation on Submit button, but I want a validator that acts as soon as focus leaves the textbox - should show me an inline error just next to the textbox, with a red font. if it validated ok, it should again show the message 'ok'.
The problem: The .js validator doesn't work. Firebug says:
$document is not defined.
$document.ready(
I also tried alert(), if i place it outside the document.ready function, it pops. when inside, it doesnt pop.
Code for registerForm.js:
$document.ready(
function ()
{
$('#registration form').validate
(
{
rules:
{
UserName: { required: true }
},
success: function (label)
{
label.Text('OK!').addClass('IsInputValid');
}
}
)
}
);
The bundle that adds this javascript is as follows:
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.unobtrusive*",
"~/Scripts/registerForm.js",
"~/Scripts/jquery.validate*"));
Finally, the view:
<div id="registration">
#using (Html.BeginForm()) {
#Html.ValidationSummary()
<fieldset>
<legend>Registration Form</legend>
<ol>
<li>
#Html.LabelFor(m => m.UserName)
#Html.TextBoxFor(m => m.UserName)
</li>
<li>
#Html.LabelFor(m => m.Email)
#Html.TextBoxFor(m => m.Email)
</li>
<li>
#Html.LabelFor(m => m.Password)
#Html.PasswordFor(m => m.Password)
</li>
<li>
#Html.LabelFor(m => m.ConfirmPassword)
#Html.PasswordFor(m => m.ConfirmPassword)
</li>
</ol>
<input type="submit" value="Register" />
</fieldset>
}
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
What could prevent the js from working?
I've already spent about 5hours trying to figure this out. Please let me know if you have any suggestions,
Regards,
#Html.TextBoxFor(m => m.UserName, new { #class = "required" })
No need for JS here. And what everyone else is saying about $document not being the correct syntax, unless you have var $document = $(document) defined somewhere.
You should use jQuery wrapper for document object:
$(document).ready(function () {
// your function
});
Is $document defined? jQuery defines a $ object. You can use that object as a function and pass it a selector, including document, and call .ready() on that:
$(document).ready(someFunction);

MVC3 using jquery.validate.unobtrusive.js and $("#form").submit() hijax not working

I have a basic form
#Html.ValidationSummary(true)
using (Html.BeginForm("Index", "Home", FormMethod.Post, new { #class = "form" }))
{
<div class="editor-label">
<label for="Name">#Html.LabelFor(model => model.Name)</label>
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
</div>
and so on. My Model is using data annotations and validation is turned on.
I'm hijaxing the form using some jquery:
<script type="text/javascript">
$("form[action='/']").submit(function () {
$.post($(this).attr("action"), $(this).serialize(), function (response) {
$("#contactForm").replaceWith($("#contactForm", response));
});
return false;
});
</script>
This works if I type the fields in correctly and submit. But the strange thing is if I enter an invalid value into one of the form fields and the validation code kicks in to highlight my mistake the submit event function I appended in the hijaxing script above is lost and a full post happens.
Any good ideas as to how I get around this?
I think when you add a submit handler to your form you are overwriting the submit handler that the jquery validation / data annotations adds.
To get around this you can add:
var theForm = $(this);
if ( theForm.valid() ) {
$.post($(this).attr("action"), $(this).serialize(), function (response) {
$("#contactForm").replaceWith($("#contactForm", response));
});
return false;
}
This will make sure the form is valid before making the POST.

CKEditor and ASP.Net MVC 3 RequiredAttribute

I've integrated CKEditor 3 (formerly FCKEditor) into my asp.net MVC (v3 to be specific) application. I have a RequiredAttribute in my model for the field that needs the editor but the client side validation doesn't work correctly with CKEditor. When I try to submit and I've entered data into CKEditor the required validation doesn't see the data. If I try resubmitting again, then it works. I've looked around online and can't find a solution. I am also using Jquery and using the Jquery adapter
http://docs.cksource.com/CKEditor_3.x/Developers_Guide/jQuery_Adapter
If someone is looking for a more generic way to do this you can add this javascript :
$(document).ready(function () {
if ($('.text-editor')) {
$('.text-editor').ckeditor();
$('input[type=submit]').bind('click', function() {
$('.text-editor').ckeditorGet().updateElement();
});
}
});
And use .text-editor css class on a textarea and it works just fine.
#Html.TextAreaFor(model => model.Description, new { #class = "text-editor" })
I find this solution eazyer than the other one, hope it can helps!
It is even simpler if you don't use the jQuery adapter:
$(function () {
$('input[type="submit"]').click(function () {
CKEDITOR.instances.Body.updateElement();
});
});
Where Body is the ID of the textarea.
For me this code does the trick, it could probably be optimized a bit but it works:
$('#newsForm').submit(function (event) {
var editor = $('#Body').ckeditorGet();
editor.updateElement();
$(this).validate().form();
});
Because I don't know in which order the eventhandlers for submit runs I make sure to both update the value and refresh the validation result.
EDIT: Updated solution
<script type="text/javascript">
//<![CDATA[
$(document).ready(function () {
$('#Body').ckeditor();
$('#newsForm').bind('submit', onFirstSubmit);
});
function onFirstSubmit(event) {
var editor = $('#Body').ckeditorGet();
editor.updateElement();
$(this).validate().form();
$(this).unbind('submit', onFirstSubmit).submit();
}
//]]>
</script>
I couldn't get it fixed with the above solutions, but this worked for me;
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Content/ckeditor/ckeditor.js")" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
CKEDITOR.replace("activiteit_details", { toolbar: 'Basic' });
CKEDITOR.replace("activiteit_verslag", { toolbar: 'Full' });
// Bind CKeditor fields on submit (To avoid problems with the RequiredAttribute)
$('input[type=submit]').bind('click', function () {
var CKactiviteit_details = CKEDITOR.instances.activiteit_details.getData();
$("#activiteit_details").val(CKactiviteit_details);
var CKactiviteit_verslag = CKEDITOR.instances.activiteit_verslag.getData();
$("#activiteit_verslag").val(CKactiviteit_verslag);
});
});
</script>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
...
<div class="editor-label">
#Html.LabelFor(model => model.activiteit_details)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.activiteit_details)
#Html.ValidationMessageFor(model => model.activiteit_details)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.activiteit_verslag)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.activiteit_verslag)
#Html.ValidationMessageFor(model => model.activiteit_verslag)
</div>
...
<p>
<input type="submit" value="Opslaan" />
</p>
</fieldset>
I also tried to use CKEditor but with no luck. I've been using CLEditor instead (along with the required attribute) and it works fine for me.
Ever thought of trying this instead?
Thanks for the answers.
Thanks to this post I've found my own solution which suits my case perfectly.
If you don't want to use click/mousedown event, but instead, want to trigger the validation on the right form-submit event you can use the following approach.
It doesn't use neither jQuery-Adapter CKEditor plugin nor click event.
And it's possible to apply it to all forms with ckeditor.
$('form').on('submit.ckeditorValidation', function () {
var $this = $(this);
var $ckeditor = $this.find('textarea.ckeditor');
// if no ckeditor for this form then do nothing
if (!$ckeditor || !$ckeditor.length) {
return true;
}
// update content from CKEditor to TextArea
var textAreaId = $ckeditor.attr('id');
CKEDITOR.instances[textAreaId].updateElement();
// trigger validation and check if the form is valid
if (!$this.valid()) {
return false;
}
// if form is valid then
// unsubscribe current event handler to avoid endless recursion
// and re-trigger form submit
$(this).off('submit.ckeditorValidation').submit();
return true;
});
i have been through the same issue and i was unable to resolve it because of one more issue that is related to it.
When ckeditor replaces the textarea, it makes it hidden and i found out that the default settings for jquery validator was to ignore the hidden elements with ":hidden" selector.
To resolve the issue, i have to update the hidden selector and update the element value. here is my code that does this in document ready event and is now working
$('#frmid').validate().settings.ignore = "input:hidden";
$('input[type="submit"]').click(function () {
$("#txtarea").val(CKEDITOR.instances["txtarea"].getData());
});

Resources