MVC 3 Client side validation on jQuery dialog - asp.net-mvc-3

I am showing lots of form using jquery dialog and I wish to add in client side validation on it. I read through some examples, saying that mvc 3 already somehow support jquery client side validation, but I tried by including the necessary script, and my form like this:
#using (Html.BeginForm("CreateFood", "Home", FormMethod.Post, new { id = "formData" }))
{
#Html.ValidationSummary(false, "Please fix these errors.")
When i try to submit my form without fill in the required field, I still dint get any message. Can anyone give me more idea / explanation / examples on this??
Really needs help here... Thanks...
UPDATE (add in the script for my dialog)
$createdialog.dialog("option", "buttons", {
"Cancel": function () {
//alert('Cancel');
$createdialog.dialog('close');
},
"Submit": function () {
var frm = $('#formData');
$.ajax({
url: '/Food/CreateFood',
type: 'POST',
data: frm.serialize(),
success: $createdialog.dialog('close')
});
}
});
Once dropped, open dialog:
// Once drop, open dialog to create food
options.drop = function (event, ui) {
// Get the ContainerImgName which food dropped at
var cimg = $(this).attr('id');
// Pass in ContainerImgName to retrieve respective ContainerID
// Once success, set the container hidden field value in the FoodForm
$.ajax({
url: '/food/getcontainerid',
type: 'GET',
data: { cImg: cimg },
success: function (result) { $('#containerID').val(result); }
});
clear();
$.validator.unobtrusive.parse($createdialog);
$createdialog.dialog('open');
};

I've faced the same problem, solved with:
$(name).dialog({
autoOpen: true,
width: options.witdth,
heigth: options.height,
resizable: true,
draggable: true,
title: options.title,
modal: true,
open: function (event, ui) {
// Enable validation for unobtrusive stuffs
$(this).load(options.url, function () {
var $jQval = $.validator;
$jQval.unobtrusive.parse($(this));
});
}
});
of course you can add the validation on the close event of the dialog, depends on what you're doing, in my case the popup was just for displaying errors so I've performed validation on load of the content. (this pop up is displaying am Action result)

For every dynamically generated form you need to manually run the validator once you inject this content into the DOM as shown in this blog post using the $.validator.unobtrusive.parse function.

Related

e.stopImmediatePropagation is not a function

This error is 9lesson.info site EDITDELETEPAGE template is
So This error is EDIT and DELETE functions have. error name is
e.stopImmediatePropagation is not a function
$(document).ready(function()
{
$(".delete").live('click',function()
{
var id = $(this).attr('id');
var b=$(this).parent().parent();
var dataString = 'id='+ id;
if(confirm("Sure you want to delete this update? There is NO undo!"))
{
$.ajax({
type: "POST",
url: "delete_ajax.php",
data: dataString,
cache: false,
success: function(e)
{
b.hide();
e.stopImmediatePropagation();
}
});
return false;
}
});
how to add add button please help me?
Possibly because you are using .live() to bind your events. From the jQuery documentation:
Since the .live() method handles events once they have propagated to the top of the document, it is not possible to stop propagation of live events.
Depending on which version of jQuery you are using, simply changing the live event handler to on (jQuery on) may fix the problem.

Unable to serialize a form that contains a tinymce editor for an Ajax call

I'm trying to post a form that contains an instance of tinyMCE editor to an action method using AJAX. My View:
<script src="#Url.Content("~/Scripts/tinymce/tiny_mce.js")" type="text/javascript"></script>
<div>
<fieldset>
#using (Html.BeginForm("SubmitNewTRForm", "LaboratoriesOrdersGrid", FormMethod.Post,
new {enctype = "multipart/form-data", #id = "newTrUploadForm" }))
{
<div style="overflow: hidden;width: 763px; height:312px; border: black solid thin;">
#Html.TextAreaFor(model => model.TestSummary, new {#class="TestSummaryEditor"})
</div>
}
</fieldset>
</div>
In the same view I instantiate the editor:
$(document).ready(function () {
tinyMCE.init({
directionality: "rtl",
width: "760",
height: "300",
language: 'fa',
// General options
mode: "textareas",
theme: "advanced",
plugins: "autolink,lists,pagebreak,style,layer,table,save,advhr,advimage,advlink,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
// Theme options
theme_advanced_buttons1: "save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect,|,sub,sup,|,charmap,iespell,advhr,|,print,|,fullscreen",
theme_advanced_buttons2: "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,cleanup,|,insertdate,inserttime,preview,|,forecolor,backcolor,|,insertlayer,moveforward,movebackward,absolute,|,blockquote,pagebreak,|,insertfile,insertimage,|,visualchars,nonbreaking,template",
theme_advanced_buttons3: "tablecontrols,|,hr,removeformat,visualaid,|,ltr,rtl,|,cite,abbr,acronym,del,ins,attribs",
theme_advanced_toolbar_location: "top",
theme_advanced_toolbar_align: "left",
theme_advanced_statusbar_location: "bottom",
theme_advanced_resizing: true,
// Skin options
skin: "o2k7",
skin_variant: "silver",
add_form_submit_trigger: false,
// Example content CSS (should be your site CSS)
content_css: "css/example.css",
// Drop lists for link/image/media/template dialogs
template_external_list_url: "js/template_list.js",
external_link_list_url: "js/link_list.js",
external_image_list_url: "js/image_list.js",
media_external_list_url: "js/media_list.js",
// Replace values for the template plugin
template_replace_values: {
username: "Some User",
staffid: "991234"
}
});
});
ANd my AJAX call:
$("form").live('submit', function (e) {
tinyMCE.triggerSave(true, true);
e.preventDefault();
var form = $("#newTrUploadForm");
if (form.valid()) {
$.ajax({
url: '#Url.Action("SubmitNewTRForm")',
data: form.serialize(),
type: 'POST',
error: function (xhr, textStatus, exceptionThrown) {
$("#errorDIV").html(xhr.responseText);
},
success: function (data) {
if (data.success) {
}
else {
}
}
});
}
});
And my AJAX call always returns an error whenever the tinyMCE editor is on the form, removing tinyMCE solves the problem, but why is this happening? I know this issue has been addresses on SO a couple of times already but I've tried all the proposed solutions and none seem to work for me, plus those solutions are somewhat outdated. During serialization in my AJAX call, i get this error:
[MissingMethodException: No parameterless constructor defined for this object.]
Any ideas?
The error I posted and the tinyMCE problem happen to be totally unrelated. The tinyMCE problem was fixed by saving the contents after preventing the default action of the button click, basically changing my AJAX call from:
$("form").live('submit', function (e) {
tinyMCE.triggerSave(true, true);
e.preventDefault();
to:
$("form").live('submit', function (e) {
e.preventDefault();
tinyMCE.triggerSave(true, true);
and the form serialzed properly and the conents of teh editor sent to the action flawlessly.
Totally irrelevant to this question, but that error posted was caused by setting my model property's type as SelectList and the form posting a SelectListItem.
Your error indicates that the model you are trying to bind to in your controller action needs a constructor like
public yourModel
{
public yourModel()
{
//your logic here
}
}
It also doesn't look like you have a 'form' in your view to post back in the first place. I have a feeling that there are multiple errors on top of each other and the paramterless constructor is just the first one.

AJAX avoid repeated code

I'm using Symfony2.1 with Doctrine2.1
I'd like to use AJAX for many features on my site , editing a title , rate an article , create an entity on the fly , etc.
My question is simple :
Do I need to create a JQuery function for each functionnality , like this :
$('#specific-functionality').bind('click', function(e){
var element = $(this);
e.preventDefault();
// the call
$.ajax({
url: element.attr('href'),
cache: false,
dataType: 'json',
success: function(data){
// some custom stuff : remove a loader , show some value, change some css
}
});
});
It sounds very heavy to me, so I was wondering if there's any framework on JS side, or a specific method I can use to avoid this. I was thinking about regrouping items by type of response (html_content , boolean, integer) but maybe something already exists to handle it nicely !
From what I understand, you are asking for lighter version of JQuery ajax method. There are direct get/post methods instead of using ajax.
$.get(element.attr('href'), {'id': '123'},
function(data) {
alert(data);
}
);
To configure error function
$.get(element.attr('href'), {'id': '123'}, function(data) {alert(data);})
.error(function (XMLHttpRequest, textStatus, errorThrown) {
var msg = jQuery.parseJSON(XMLHttpRequest.responseText);
alert(msg.Message);
});
Also, you can pass callback function to do any synchronous operations like
function LoadData(cb)
{
$.get(element.attr('href'), { 'test': test }, cb);
}
And call
LoadData(function(data) {
alert(data);
otherstatements;
});
For progress bar, you use JQuery ajaxStart and ajaxStop functions instead of manually hiding and showing it. Note, it gets fired for every JQuery AJAX operation on the page.
$('#progress')
.ajaxStart(function () {
//disable the submit button
$(this).show();
})
.ajaxStop(function () {
//enable the button
$(this).hide();
});
Instead of $('#specific-functionality').bind('click', function(e){, try this:
$(".ajax").click(function(){
var url = $(this).attr("href") ;
var target = $(this).attr("data-target") ;
if (target=="undefined"){
alert("You forgot the target");
return false ;
}
$.ajax(....
And in html
<a class="ajax" href="..." data-target="#some_id">click here </a>
I think it is the simplest solution. If you want some link to work via ajax, just give it class "ajax" and put data-target to where it should output results. All custom stuff could be placed in these data-something properties.

jquery live() appending click events causing multiple clicks

I have some strange behaviour going on with the jQuery ajax functionality in my asp.net MVC3 application.
I have several boxes of data each containing a link to open a popup and change the data in each box. To do this I've added a jquery live() click event to process the data via a jQuery ajax call. In the "success" method of the ajax call, i take the return data and open a UI Dialog popup (a partial view) which contains a list of radio buttons. I select a different radio button and press 'close' - the close button fires another live() click event, processes that new data via an ajax call which refreshes the data in the box on the main page.
This works perfectly first time. If you then click to change it again, the popup opens, allows you to select a new value, but this time pressing close on the popup triggers two click events which throws an null error in my MVC controller.
If you repeat this process it triggers 3 click events, so it's clear that live() is appending these events somewhere.
I've tried using on() and click(), but the page itself is made up of panels loaded in via ajax so I used live() to automatically bind the events.
Here is the code I'm using:
HTML
<p><!--Data to update goes here--></p>
Update Data
First Click event calling popup with Partial View
$('a.adjust').live('click', function (e) {
var jsonData = getJsonString(n[1]);
var url = '#Url.Action("ChangeOptions", "Search")';
var dialog = $('<div id="ModalDialog" style="display:none"></div>').appendTo('body');
// load the data via ajax
$.ajax({
url: url,
type: 'POST',
cache: false,
contentType: "application/json; charset=utf-8",
data: jsonData,
success: function (response) {
dialog.html(response);
dialog.dialog({
bgiframe: true,
modal: true
}
});
}
});
e.preventDefault();
});
Second click event the takes the new info to return updated partial view
$('a#close').live('click', function (event) {
var jsonData = getJsonString(n[1]);
var url = '#Url.Action("GetChangeInfo", "Search")';
$.ajax({
url: url,
type: 'POST',
contentType: "application/json; charset=utf-8",
data: jsonData,
success: function (response) {
$('#box-' + #column).html(response); //this refreshes the box on the main page
},
error: function () {
}
});
$('#ModalDialog').dialog('close');
event.preventDefault();
});
Anybody know what might be happening here, and how I could resolve it?
Use namespaces to unbind previous click binds like this:
$('a.adjust').unbind('click.adjustclick');
Then bind the click action to a.adjust:
$('a.adjust').bind('click.adjustclick', function(){
//your code here
//note the return false, this prevents the browser from visiting the URL in the href attribute
return false;
});
If i understand you correctly, you try to run the second click action when the dialog is closed. Therefor I would use the build in close function for the dialog like this:
$('a.adjust').bind('click.adjustclick', function(){
var jsonData = getJsonString(n[1]);
var url = '#Url.Action("ChangeOptions", "Search")';
var dialog = $('<div id="ModalDialog" style="display:none"></div>').appendTo('body');
// load the data via ajax
$.ajax({
url: url,
type: 'POST',
cache: false,
contentType: "application/json; charset=utf-8",
data: jsonData,
success: function (response) {
dialog.html(response);
dialog.dialog({
bgiframe: true,
modal: true,
close: function(){
var jsonData2 = getJsonString(n[1]);
var url2 = '#Url.Action("GetChangeInfo", "Search")';
$.ajax({
url: url2,
type: 'POST',
contentType: "application/json; charset=utf-8",
data: jsonData2,
success: function (response2) {
$('#box-' + #column).html(response2); //this refreshes the box on the main page
},
error: function () {
}
});
}
}
});
}
});
});
If you are using your own button a#close, bind a click event to it to close the dialog, it will automatically fire the close function for the dialog.
$('a#close').unbind('click.closedialog');
$('a#close').bind('click.closedialog', function () {
$('#ModalDialog').dialog('close');
return false;
}
Try this:
$('a#close').unbind('click').bind('click', function (event) {
//Your Code
});

Updating a dropdown via knockout and ajax

I am trying to update a dropdown using knockout and data retrieved via an ajax call. The ajax call is triggered by clicking on a refresh link.
The dropdown is successfully populated when the page is first rendered. However, clicking refresh results in clearing the dropdown instead of repopulating with new data.
Html:
<select data-bind="options: pages, optionsText: 'Name', optionsCaption: 'Select a page...'"></select>
<a id="refreshpage">Refresh</a>
Script:
var initialData = "[{"Id":"231271443653720","Name":"Car2"},{"Id":"439319486078105","Name":"Electronics1.2"},{"Id":"115147185289433","Name":"Product"},{"Id":"145033098963549","Name":"Product2"}]";
var viewModel = {
pages : ko.mapping.fromJS(initialData)
};
ko.applyBindings(viewModel);
$('#refreshpage').click(function() {
$.ajax({
url: "#Url.Action("GetPageList", "FbWizard")",
type: "GET",
dataType: "json",
contentType: "application/json charset=utf-8",
processData: false,
success: function(data) {
if (data.Success) {
ko.mapping.updateFromJS(data.Data);
} else {
displayErrors(form, data.Errors);
}
}
});
});
Data from ajax call:
{
"Success": true,
"Data": "[{"Id":"231271443653720","Name":"Car2"},{"Id":"439319486078105","Name":"Electronics1.2"},{"Id":"115147185289433","Name":"Product"},{"Id":"145033098963549","Name":"Product2"}]"
}
What am I doing wrong?
The problem you have is that you are not telling the mapping plugin what to target. How is it suppose to know that the data you are passing is supposed to be mapped to the pages collection.
Here is a simplified version of your code that tells the mapping what target.
BTW The initialData and ajax result were the same so you wouldn't have noticed a change if it had worked.
http://jsfiddle.net/madcapnmckay/gkLgZ/
var initialData = [{"Id":"231271443653720","Name":"Car2"},{"Id":"439319486078105","Name":"Electronics1.2"},{"Id":"115147185289433","Name":"Product"},{"Id":"145033098963549","Name":"Product2"}];
var json = [{"Id":"231271443653720","Name":"Car2"},{"Id":"439319486078105","Name":"Electronics1.2"},{"Id":"115147185289433","Name":"Product"}];
var viewModel = function() {
var self = this;
this.pages = ko.mapping.fromJS(initialData);
this.refresh = function () {
ko.mapping.fromJS(json, self.pages);
};
};
ko.applyBindings(new viewModel());
I removed the jquery click binding. Is there any reason you need to use a jquery click bind instead of a Knockout binding? It's not recommended to mix the two if possible, it dilutes the separation of concerns that KO is so good at enforcing.
Hope this helps.

Resources