Cannot get tinyMCE textarea to validate in MVC3 - asp.net-mvc-3

I have three partial views within a view that are toggled via radiobutton selection. Each partial view has it's own submit input and two of the partial views contain a tinyMCE textarea. When I only had one partial that contained a tinyMCE textarea, I was able to get that textarea to validate using .triggerSave(), but now that I have added the second tinyMCE textarea, I can't get either of the tinyMCE textareas to pass validation.
I tried many of the solutions found on similar questions here on SO, but I have not been successful in getting these textareas to pass validation.
Here is the tinyMCE pertinent code on the first partial:
<script type="text/javascript">
$(document).ready(function () {
tinyMCE.init({
mode: "specific_textareas",
editor_selector: "mceEditorForAddRow",
theme: "simple",
width: "500",
height: "300"
});
});
#using(Html.BeginForm("_AddSchemaRow","Database_Schema")
{
#Html.ValidationSummary(true)
<script type="text/javascript">
$("#CreateRow").click(function () {
tinyMCE.triggerSave();
});
</script>
<table>
....
....
<tr>
<td>
#Html.LabelFor(model => model.SchemaElement)
</td>
<td>
#Html.TextAreaFor(model => model.SchemaElement, new { #class = "mceEditorForAddRow" })
#Html.ValidationMessageFor(model => model.SchemaElement)
</td>
</tr>
....
....
</table>
<p>
<input id="CreateRow" type="submit" value="Create" />
</p>
}
Here is the contoller's action for this first partial:
public ActionResult _AddSchemaRow(int id)
{
SchemaRow schemaRow = new SchemaRow();
schemaRow.DatabaseSchemaID = id;
schemaRow.SchemaIndex = DatabaseSchema.GetSchemaHeadersByDatabaseSchemaID(id).Count() + 1;
return PartialView(schemaRow);
}
Here is the controller's POST action for this first partial:
[HttpPost]
[ValidateInput(false)]
public ActionResult _AddSchemaRow(SchemaRow schemaRow)
{
if (ModelState.IsValid)
{
DatabaseSchemaViewModel vm = new DatabaseSchemaViewModel(DatabaseSchema.GetDatabaseSchemaByID(schemaRow.DatabaseSchemaID));
vm.SchemaRowsAndHeaders = DatabaseSchemaViewModel.GetSchemaRowsAndHeadersBySchemaID(schemaRow.DatabaseSchemaID);
if (SchemaRow.Create_SchemaRow(schemaRow))
{
return RedirectToAction("Edit", new { id = schemaRow.DatabaseSchemaID });
}
else
return PartialView(schemaRow);
}
else
return PartialView(schemaRow);
}
The second partial is set up just like the first partial above, except contains a "SchemaHeader" rather than a "SchemaRow" in all applicable fields including the submit input id being "CreateSchemaHeader". I think example code should provide enough description of my problem. I can add the other partial's code if needed. Thanks in advance for any help in finding a solution.

I was able to finally figure it out. The solution was to add click function after the input that the input that causes the postback.
Example:
<p>
<input id="CreateRow" type="submit" value="Create" />
</p>
<script type="text/javascript">
$("#CreateRow").click(function () {
tinyMCE.triggerSave();
});
</script>

Related

popup a dialog and submit partial view in asp.net mvc

So what I am trying to do here is that in the View,
when I click on the button, I want to pass some values generated from the foreach loop (in my case Country and City) to the javascript function.
Inside that javascript function, I want to open up a dialog(partial view) by passing those values (countryName, cityName) to the controller.
Hence in my controller, it will pass those values to the partial view which will be appeared as a dialog and can submit the form.
I've tried with the version without the pop-up dialog (it worked), but having a hard time doing it with a dialog. #3 works btw, but I think I am having a trouble with #1 and #2. Any help would be appreciated. Thanks.
View:
#model IEnumerable<test.Models.Employee>
<table class="table">
<tr>
<th>Country</th>
<th>City</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Country)
</td>
<td>
#Html.DisplayFor(modelItem => item.City)
</td>
<td>
<button onclick="OpenDialog(item.Country, item.City)">
Open Dialog
</button>
</td>
</tr>
}
</table>
<div id="dialog"></div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script src="~/Scripts/jquery-ui-1.12.0.js"></script>
<script>
function OpenDialog(countryName, cityName) {
$('#dialog').dialog({
autoOpen: true,
width: 400,
resizable: false,
title: 'My Table',
modal: true,
open: function(event, ui) {
$(this).load('#Url.Action("getEmployee", "Employee", new
{
country = countryName,
city = cityName
})');
},
buttons: {
"Close": function () {
$(this).dialog("close");
}
}
});
}
</script>
}
Controller:
public ActionResult getEmployee(string country, string city)
{
var viewModel = new EmployeeViewModel()
{
Country = country,
City = city
};
return PartialView("EmployeeDialog", viewModel);
}
Partial View:
#model test.ViewModels.EmployeeViewModel
#using (Html.BeginForm("PostEmployee", "Employee", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.Country)
#Html.HiddenFor(model => model.City)
#Html.EditorFor(model => model.Comments)
<input type="submit" value="Submit"/>
}
#Url.Action() is razor code and is parsed in the server before its sent to the view. countryName and cityName are javascript variables and do not even exist at that point (they are not in scope). Change the code in the OpenDialog() function to
var url = '#Url.Action("getEmployee", "Employee")';
var data = { country: countryName, city: cityName };
$(this).load(url, data);
As a side note, there is really no need to be calling the server each time to return values that you already have in the view. You could just render the form in the dialog initially (for a default EmployeeViewModel and then in the OpenDialog just set the values of the inputs for properties Country and City, for example $('#Country').val(countryName);

Saving multiple partial views from one main page

Here is my requirement :
I am designing a page to add a vehicle to the database :
Normal vehicle information [Model - Inventory]
Some other features [Model - IList]
Here is my index.cshtml page
#model Model.ViewModel.VehicleViewModel
<div>
<div class='col-md-12'>
<div class="form-group">
<input id="mainFormSubmit" type="button" value="Save" class="btn btn-default" />
</div>
</div>
#{Html.RenderPartial("~/Views/Shared/_InventoryPartial.cshtml", Model.InventoryVM);}
#{Html.RenderPartial("~/Views/Shared/_StandardFeaturePartial.cshtml", Model.StandardFeatures);}
</div>
<script type="text/javascript">
$('#mainFormSubmit').click(function () {
$('#InventoryForm').submit();
$("#StandardFeatureForm").submit();
});
</script>
This is my view model class
public class VehicleViewModel
{
public InventoryViewModel InventoryVM { get; set; }
public IList<StandardFeature> StandardFeatures { get; set; }
}
The Inventory partial view [_InventoryPartial.cshtml]
#model Model.ViewModel.InventoryViewModel
#{
var options = new AjaxOptions() { HttpMethod = "Post" };
}
<div class="container">
<div class="row">
<div class="col-md-12">
#using (Ajax.BeginForm("InventorySave", "AddVehicle", options, new { id = "InventoryForm" }))
{
<fieldset>
<legend>Inventory Info</legend>
<div class='col-md-6'>
<!-- VIN input-->
<div class="form-group">
#Html.LabelFor(x => x.VIN, new { #class = "col-md-4 control-label" })
<div class="col-md-7">
#Html.TextBoxFor(x => x.VIN, new { #class = "form-control", #placeholder = "VIN" })
</div>
</div>
</div>
</fieldset>
}
The standard feature partial view [_StandardFeaturePartial.cshtml]
==
#model IEnumerable<Model.DomainModel.StandardFeature>
#{
var options = new AjaxOptions() { HttpMethod = "Post" };
}
<div class="container">
<div class="row">
<div class="col-md-12">
#using (Ajax.BeginForm("StandardFeatureSave", "AddVehicle", options, new { id = "StandardFeatureForm" }))
{
When I am clicking on index page SAVE button, only
$('#InventoryForm').submit();
$("#StandardFeatureForm").submit();
last one(StandardFeatureForm) is executing.
Please let me know if this process is correct, and what could be the reason of this issue.
You should not call the submit method twice. Depending of the browser you can face different issues :
the form submission causes the browser to navigate to the form action and the submission
of the first may prevent the submission of the second
The browser could detected there are two requests and discards the
first submit.
In your case it will be easier to wrap your two partial views inside a unique form.
#using (Ajax.BeginForm("InventorySave", "AddVehicle", FormMethod.Post, new { id = "InventoryForm" }))
{
#{Html.RenderPartial("~/Views/Shared/_InventoryPartial.cshtml", Model.InventoryVM);}
#{Html.RenderPartial("~/Views/Shared/_StandardFeaturePartial.cshtml", Model.StandardFeatures);}
}
However when the partial views render they are not generating the correct name attributes for the larger modelModel.ViewModel.VehicleViewModel you want to use :
public void InventorySave(VehicleViewModel vehicleViewModel) {}
In this case you should use EditorTempmlate instead of partial views. It's simple to do from your partial views and this post should help you :Post a form with multiple partial views
Basically, drag your partials to the folder ~/Shared/EditorTemplates/
and rename them to match the model name they are the editor templates
for.
Finally something like :
#model Model.ViewModel.VehicleViewModel
#using (Html.BeginForm("InventorySave", "AddVehicle", FormMethod.Post, new { id = "InventoryForm" }))
{
#Html.EditorFor(m => m.InventoryVM);
#Html.EditorFor(m => m.StandardFeatures});
}
The Ajax.BeginForm helper already has a submit event associated to it which creates an Ajax POST request. When you are manually submitting your form using $('#InventoryForm').submit();, you're calling both and the submit events which can have strange side effects.
There are a few ways around this. Here is one solution
Change your forms to a regular HTML form using the Html.BeingForm helper.
Amend your script to create ajax requests and use the form data
$('#InventoryForm').submit(function(e) {
e.preventDefault();
$.post($(this).attr("action"), $(this).serialize(), function(r) {
//Do something
});
});
$('#StandardFeatureForm').submit(function(e) {
e.preventDefault();
$.post($(this).attr("action"), $(this).serialize(), function(r) {
//Do something
});
});
Hope this helps

MVC3 unobtrusive validators not being written into partial page

When the following code is retrieved via an ajax call no validators are written into the view. Any number of these partial views might be added to the page and the textbox gets a datepicker, so that's why the unique id is generated. I certainly appreciate any help.vie
#using Nautilus.Core.Model.Enumeration
#using Nautilus.Web.Models
#using Nautilus.Web.Views.Tools
#model IntensityHistoryModel
<tr>
<td class='removeIntensityScore' title='Click to remove this item.'></td>
<td>
<span></span>
</td>
<td>
#Html.ValidationMessageFor(m => m.IntensityDateGUID)
#Html.TextBoxFor(m => m.IntensityDate, new { id = Model.IntensityDateGUID, #class = "intensityScoreDate", style = "width:120px" })
</td>
<td>
#Html.DropDownList("IntensityScore", ViewHelper.GetSelectListWithDescriptionFromEnum<IntensityScore.Values>("", new[] { "0" }), " -- Select -- ", new { style = "width:150px;margin:0" })
</td>
</tr>
When you do the ajax call, in the callback function you have to call again the validation.
Something like that
$("#myDiv").load($("#myA").attr("href"), function () {
$.validator.unobtrusive.parse("#myFormPartial");
});
It's not including the validation data attributes because the elements are not in a form. The workaround is to initialize a FormContext for your partial view:
#{
ViewContext.FormContext = new FormContext();
}
<tr><!-- your partial content --></tr>

generating pop up when button is clicked

when a submit button is clicked i want to generate a pop up showing the list of items. The code i tried to create pop up is as follows:`
Index View:
<script type="text/javascript">
$('#popUp').Hide();
$('#button').click(function () {
$('#popUp').click();
});
</script>
<div class="left-panel-bar">
#using (Html.BeginForm(FormMethod.Post))
{
<p>Search For: </p>
#Html.TextBox("companyName",Model);
<input id="button" type="submit" value="Submit" />
}
</div>
<div id="popUp">
#Html.ActionLink("Get Company List", "CreateDialog", "Company", null, new
{
#class = "openDialog",
data_dialog_id = "emailDialog",
data_dialog_title = "Get Company List"
});
</div>
but i got trouble using this code.. when i click the submit button it opens another page instead of popup. The controller code is as follows:
[HttpPost]
public ActionResult Index(Companies c)
{
Queries q1 = new Queries(c.companyName);
if (Request.IsAjaxRequest())
return PartialView("_CreateDialog", q1);
else
return View("CreateDialog", q1);
}
You could use AJAX:
<script type="text/javascript">
$(function() {
$('form').submit(function() {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function(result) {
$('#popUp').html(result);
}
});
return false;
});
});
</script>
<div class="left-panel-bar">
#using (Html.BeginForm())
{
<p>Search For: </p>
#Html.TextBox("companyName", Model);
<input id="button" type="submit" value="Submit" />
}
</div>
<div id="popUp">
</div>
Now ehn the form is submitted, an AJAX request will be sent to the Index POST action and since inside you test if the request was an AJAX request it will return the _CreateDialog.cshtml partial view and insert it into the #popUp div. Also it is important to return false from the form submit handler in order to cancel the default even which is to redirect the browser away from the current page.

Using Jquery to collect data, use data to get a Partial View from the controller, and append the passed information to the end of a page

I am attempting to append a partial view to the end of my 'currently displayed page' when a selection from a dropdown menu is chosen.
This is the dropdown from my view:
<div>
#Html.DropDownListFor(x => x.DropDownInfo, Model.Info, "DefaultSelection")
#Html.ValidationMessageFor(model => model.Courses)
</div>
I am in most need here in my Jquery. What do I need to do to append the PartialView that is returned by my controller (pasted below)? My current Jquery:
$(document).ready(function() {
$("#DropDownInfo").change(function() {
var strSelected = "";
$("#DropDownInfo option:selected").each(function() {
strSelected += $(this)[0].value;
});
var url = "/Controller/PreFillMethod/?MethodString=" + strSelected;
$.post(url, function(data) {
//*****
// Assuming everything else is correct,
// what do I do here to have my partial view returned
// at the end of the currently displayed page?
//*****
});
});
});
This is the part of my controller that replies with a PartialView (I want the string from the dropdown selection to be passed into this controller to ultimately be used to fill in a field in the PartialView's form) :
public PartialViewResult PreFillCourse(string selectedFromDropDown)
{
ViewBag.selectedString = selectedFromDropDown;
MyViewModel preFill = new MyViewModel
{
Title = selectedFromDropDown, // I am using this to pre-fill a field in a form
};
return PartialView("_PartialViewForm", preFill);
}
The Partial View (in the case that it matters):
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>CourseTemplates</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
I am open to suggestions if I am approaching the situation entirely incorrectly.
My goal is to have a user select a 'template' from the drop-down menu and have that template's data autopopulate into a form below the drop-down.
My Jquery is very rough - I am using this post as a guide
you should have a div in your view
<div id ="divToAppend">
</div>
then append the partial view to your div
$(document).ready(function() {
$("#DropDownInfo").change(function() {
var strSelected = "";
$("#DropDownInfo option:selected").each(function() {
strSelected += $(this)[0].value;
});
var url = "/Controller/PreFillMethod/?MethodString=" + strSelected;
$.post(url, function(data) {
$('#divToAppend').html(data);
//*****
// Assuming everything else is correct,
// what do I do here to have my partial view returned
// at the end of the currently displayed page?
//*****
});
});
});

Resources