Cannot link back to MVC view via javascript - javascript

I have an Index View and when I click the Edit button, I post to the Edit View (via the Controller) and display a bootstrap modal popup.
By posting to the Edit View, the Controller/View automatically handle getting and displaying the correct data on the modal popup.
Once I'm on my Edit View with the dialog box appearing and I click on the Close button, I simply want to link back to the Index page again; but instead, am getting an error with the path of the url. The new path I want to link to is being "tacked on" to the original path instead of replacing it.
I'm using the Url.Action method inside the click event of the Close button (of which I verified it's hitting) and have verified the location.href url is exactly what is in the url variable as you see in the code.
What do I need to do to correctly link back to the Index url?
Index View
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span>Edit
Edit Controller
// GET: Categories/Edit/5
public async Task<ActionResult> Edit(short id)
{
if (id == 0)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Category category = await db.GetCategoryIDAsync(id);
if (category == null)
{
return HttpNotFound();
}
return View(category);
}
Edit View
#model YeagerTechDB.Models.Category
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="modal" id="categoryEditModal" tabindex="-1" role="dialog" aria-labelledby="categoryModal-label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="categoryModal-label">Category Description</h4>
</div>
<div class="modal-body">
<div class="form-group">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.CategoryDescription, new { #class = "control-label required col-offset-1 col-lg-3 col-md-3 col-sm-3 col-xs-3" })
<div class="col-lg-8 col-md-8 col-sm-8 col-xs-8">
#Html.EditorFor(model => model.CategoryDescription, new { #class = "form-control" } )
#Html.ValidationMessageFor(model => model.CategoryDescription, "", new { #class = "text-danger" })
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-default" id="btnCloseCategory">Close</button>
<button type="submit" class="btn btn-primary" id="btnSaveCategory">Save</button>
</div>
</div>
</div>
</div>
<div>
#Html.Hidden("categoryEditUrl", Url.Action("Edit", "Category", new { area = "Categories" }))
#Html.Hidden("catID", Model.CategoryID)
</div>
#section Scripts {
<script>
$(document).ready(function ()
{
if (typeof contentEditCategory == "function")
contentEditCategory()
});
</script>
}
JS for Edit View
$('#btnCloseCategory').click(function (e)
{
var url = '#Url.Action("Index", "Category", new { area = "Categories" })';
location.href = url;
return false;
});
Image of modal popup
Image of error

Assuming your javascript is in an external file you could do the following:
Attach the url to your button within your view with a data attribute as follows:
<button type="submit" class="btn btn-default" id="btnCloseCategory"
data-url="#Url.Action("Index", "Category", new { area = "Categories" })">Close</button>
Then pull back the url with the data method as follows:
$('#btnCloseCategory').click(function (e)
{
var url = $(this).data('url');
location.href = url;
return false;
});

Try changing type="submit" to type="button" for your Close button.
<button type="button" class="btn btn-default" id="btnCloseCategory">Close</button>

Related

C# MVC Razor Partial to Upload a File in a Modal with Postback Message also in a Modal

I have a simple partial page to upload a file nested in a modal. I am not using ajax for the actions. There are 2 items in the controller
[HttpGet]
public ActionResult UploadFile()
{
return View();
}
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase file)
{
try
{
if (file.ContentLength > 0)
{
string _FileName = Path.GetFileName(file.FileName);
string _path = Path.Combine(Server.MapPath("~/UploadedDocuments"), _FileName);
file.SaveAs(_path);
}
ViewBag.Message = "File Uploaded Successfully!!";
return PartialView("UploadFile");
}
catch
{
ViewBag.Message = "File upload failed!!";
return PartialView("UploadFile");
}
}
The problem I am having is on postback it returns the partialView and not in the modal. I actually would like to see the postback message in a new modal dialog box.
I read an article that gave the idea of making a separate partial page with the message in it. To me that seems like a waste. Any idea how I can accomplish this with what I have or do I just have to do the form using JavaScript / Ajax?
Here is the form
#{
ViewBag.Title = "UploadFile";
Layout = null;
}
#Scripts.Render("~/Scripts/jquery-3.3.1.min.js")
<!-- MODAL -->
<div class="modal-header">
<h4 class="modal-title" id="exampleModalLabel"> <span class="glyphicon glyphicon-upload"></span> Upload File </h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
#using (Html.BeginForm("UploadFile", "Document", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
#Html.TextBox("file", "", new { type = "file" }) <br />
<input type="submit" value="Upload" />
#ViewBag.Message
</div>
}
This is where the Modal is initiated - on index page with button.
<button type="button" class="btn btn-primary" id="Upload" onclick="createModal('#Url.Action("UploadFile", "Document")')">
<span class="glyphicon glyphicon-upload"></span> Upload
</button>
//////////
/////////
<div class="modal fade" id="myModal" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" data-backdrop="static" data-keyboard="false">
<div class="modal-dialog">
<div class="modal-content" id="modelContent">
</div>
</div>
</div>
<script type="text/javascript">
function createModal(url) {
$('#modelContent').load(url);
$('#myModal').modal('show');
}
$(function () {
// when the modal is closed
$('#myModal').on('hidden.bs.modal', function () {
// remove the bs.modal data attribute from it
$(this).removeData('bs.modal');
// and empty the modal-content element
$('#myModal .modal-content').empty();
});
});
</script>

jquery function firing even though condition is false

This is a real mystery for me and the other developers who have looked at it. I have a jquery function and within the function I have an if statement. There is some code within the statement body that I want executed when the condition is true, but not executed when the condition is false. Pretty simple. However, the code within the body is being executed, EVEN when the condition is false. The variable in the condition is called delayExists (which is outside the function). I tested using a variable (called test) within the function and "forced" the condition to be true - ONLY in this scenario is the if statement working correctly. I've stepped through the code using Chrome Developer tools and can see when delayExists becomes true yet the condition appears to be ignored. I've tried to include the pertinent code below. Please let me know I need to provide more.
<!-- at model specifies the type of object the view expects -->
#model atdaem
<div class="tab-pane" id="tab_delays">
<div class="row">
<div class="col-xs-12">
#(Html.Kendo().Grid<atdlm>().Name("delays-grid").Columns(columns =>
{
columns.Bound(c => c.Id).HeaderTemplate(" ").Width(1).ClientTemplate("<span style=\"white-space:nowrap;\">" + "<button type=\"button\" class=\"btn btn-social-icon btn-linkedin\" " + "data-toggle=\"modal\" data-target=\"\\#delayAddModal\" data-guid=\"#=Id#\" data-name=\"#=LocationName#\" " +
"data-title=\"Edit Delay\" >" + "<i class=\"fa fa-edit\"></i></button>" + "</span>");
;
}).DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Type(HttpVerbs.Post)
.Action("ActualDelayList", "TrainActivity")
.Data("actualJobTaskId")))
.Events(events => events.DataBound("delaysDatabound")))
<div class="pull-right top-buffer">
<button type="button" class="btn bg-green" data-toggle="modal"
data-title="Add Delay"
data-target="#delayAddModal">
<i class="fa fa-plus-square"></i>
Add delay
</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="delayAddModal" tabindex="-1" role="dialog" aria-labelledby="delayAddLabel">
<div class="modal-dialog" role="document">
<!-- Modal content -->
<div class="modal-content">
<div class="modal-header">
<!-- This "x" button is for dismissing the modal -->
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="delayAddLabel">Add Delay</h4>
</div>
<div class="modal-body">
<form name="delay-form" id="delay-form">
#Html.HiddenFor(m => m.atdId, new { id = "atdId" })
#Html.HiddenFor(m => m.ajtId)
#*Original:*#
<div class="form-group">
<!-- Renders floating text ("Subdivision") above the select options -->
#Html.LabelFor(m => m.SubdivisionId, new { #class = "field-label always-visible" })
<!-- ID for select element -->
<!-- Renders select class="select" id="SubdivisionId" name="SubdivisionId"><option value="4429faa8-5ad4-4adf-adde-ec7cf88ed9e9" innerHTML "Caltrain"-->
#Html.DropDownListFor(m => m.SubdivisionId, Model.AvailableSubdivisions, new { #class = "select" })
#Html.ValidationMessageFor(m => m.SubdivisionId)
</div>
<div class="row">
<!--Start milepost -->
<div class="col-xs-6">
<div class="form-group">
#Html.LabelFor(m => m.StartMilepost, new { #class = "field-label" })
#Html.TextBoxFor(m => m.StartMilepost, new { #class = "form-control", placeholder = Html.DisplayNameFor(m => m.StartMilepost) })
#Html.ValidationMessageFor(m => m.StartMilepost)
</div>
</div>
<!-- End milepost -->
<div class="col-xs-6">
<div class="form-group">
#Html.LabelFor(m => m.EndMilepost, new { #class = "field-label" })
#Html.TextBoxFor(m => m.EndMilepost, new { #class = "form-control", placeholder = Html.DisplayNameFor(m => m.EndMilepost) })
#Html.ValidationMessageFor(m => m.EndMilepost)
</div>
</div>
</div>
<!-- Location -->
<div class="form-group">
#Html.LabelFor(m => m.LocationId, new { #class = "field-label always-visible" })
<select id="LocationId" name="LocationId" class="select">
#foreach (var loc in Model.AvailableLocations)
{
<option value="#loc.Id" data-milepost="#loc.Milepost">#loc.Name</option>
}
</select>
#Html.ValidationMessageFor(m => m.LocationId)
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<!-- call to js function-->
<button id="delayAddButton" type="button" class="btn btn-primary" data-title="Add Delay">Add Delay</button>
</div>
</div>
</div>
</div>
<script>
var delayExists = false;
//the jquery function is listening for the element with the id #delayAddModal (which is also used for delayEdit); when that modal is shown (by someone clicking
// on the Add Delay button which has a data-target that points to the modal), just before the modal appears this fuction executes)
$("#delayAddModal")
.on("show.bs.modal",
function(event) {
var button = $(event.relatedTarget); // Button that triggered the modal
var modal = $(this);
var title = button.data('title'); // get New title from data-title attribute
var delId = button.data("guid");
var name = button.data("name");
var conditionalVariable = 1;
var updateButtonValue = "Save Edit";
modal.find('.modal-title').text(title); // set title to New title
modal.find('#delayAddButton').text(updateButtonValue); // set button value to Edit Delay
$.ajax({
type: "GET",
url: "/TrainActivity/GetDelayDataForEditing/" + "?delayId=" + delId,
dataType: 'json',
success: function(data) {
delayExists = true;
modal.find('');
var sub = data.SubdivisionId;
$.getJSON('/TrainActivity/LocationBySubdivisionList?id=' + sub,
function(locs) {
// the stuff that needs to happen before the parent ajax completes needs to go in here
$('select#SubdivisionId').val(data.SubdivisionId).trigger('change');
$('#StartMilepost').val(data.StartMilepost);
$('#EndMilepost').val(data.EndMilepost);
$('#LocationId').val(data.LocationId).trigger('change');
//$('select#LocationId').val(data.LocationId).trigger('change');
});
},
error: function() { alert("error in Delay Edit"); }
});
});
//matches location based on input in Start Milepost
$(document)
.ready(function() {
var test = true;
//matches location based on input in Start Milepost
var button = $(event.relatedTarget); // Button that triggered the modal
var delId = button.data("guid");
if (test == false) {
//if (delayExists == false) {
$("#StartMilepost").change(function() {
$("#EndMilepost").val($(this).val());
//nearestMilepost();
});
}
#*function nearestMilepost()
{
//var mile = parseFloat($(this).val());
var mile = $("##Html.IdFor(m => m.StartMilepost)").val();
var sub = ($("#SubdivisionId").val());
var locationId = $('#LocationId option').filter(function () {
return parseFloat($(this).data('milepost')) >= mile
}).val();
$("#LocationId").val(locationId).change();
}
});
//changing the subdivision changes the locations available in the location box
#*$("#SubdivisionId").change(function () {
var sub = $(this).val();
$.getJSON('#Url.Action("LocationBySubdivisionList", "TrainActivity")?id=' + sub,
function (locs) {
var list = $('##Html.IdFor(model => model.LocationId)');
list.find('option').remove();
$(locs).each(function (index, loc) {
list.append('<option value="' + loc.Id + '" data-milepost="'+ loc.Milepost+'">' + loc.Name + '</option>');
});
nearestMilepost();
});
});*#
});
</script>
The misunderstanding is here:
if (delayExists == false) {
$("#StartMilepost").change(function() {
$("#EndMilepost").val($(this).val());
// etc.
});
}
That check happens once, at startup. Is delayExists false? Yes (at startup), so we add that handler. Which will always run all of the code within.
If you want to check the flag everytime #StartMilepost changes, you need to do that:
$("#StartMilepost").change(function() {
if (delayExists == false) {
$("#EndMilepost").val($(this).val());
// etc.
}
});

MVC Bootstrap Partial View ValidationMessageFor execute on loading Page

Im am doing an MVC, Bootstrap App.
I open a Bootstrap Partial View from Jquery passing Model as Parameter.
From Controller I return Partial View and I open it from Jquery.
The Problem I found, is that ValidationMessageFor is executed when Partial View is loaded... I can not find why.
The process is like this... I have an Image that called a JavaScript function...
img id="btnEmail" src="~/Content/Images/Email.png" onclick="btnEmail('param1',Param2)"
Here is My Jquery
function btnEmail(nick, user_id) {
--validate if user is logged and call function that call Partial View
if (SearchLogin())
SendMail();
}
function SendMail() {
user_id = $('#CommentUser_id').val();
nick = $('#LblCommentName').val();
if (user_id == $('#User_id').val())
return;
var model = { Object_id: $("#Upload_id").val(), Nick: nick, UserDestination_id: $("#User_id").val(), Parent_id: null, UserOrigin_id: user_id};
$.ajax(
{
type: "POST",
url: '#Url.Action("Email", "Contact")',
data: model,
success: function (result) {
$("#myModalContact").html(result).modal({ backdrop: "static" });
},
});
"static" });
}
Here is my
Controller Method
public async Task<ActionResult> Email(ContactModel model)
{
return PartialView("_Contact", model);
}
And Here is my Partial View
If I called my Partial View like this
<div class="modal fade" id="myModalContact" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
#Html.Partial("~/Views/Contact/_Contact.cshtml", new TableAvivaVoz.Models.ContactModel() { Object_id = Model.upload.Upload_id, Nick = Model.upload.Nick, UserDestination_id = Model.upload.User_id, Parent_id = null,UserOrigin_id=Model.User_id });
</div>
it Works fine...
here is part of My Partial View
#model TableAvivaVoz.Models.ContactModel
#{
AjaxOptions ajaxOpts = new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "sucessContact",
};
}
#using (Ajax.BeginForm("XXX", "Contact", ajaxOpts))
{
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">
</h4>
</div>
<div class="myPartialContact">
<div class="alert alert-success hidden">
</div>
</div>
#Html.AntiForgeryToken()
<div style="padding-bottom:220px">
<div class="modal-body">
<div class="col-md-10">
#Html.TextAreaFor(model => model.Description, 10, 80, new { #class = "txtDescQ", placeholder = "Ingresa un mensaje", #rows = 8, onclick = "OcultarRecomend();" })
#Html.ValidationMessageFor(model => model.Description, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="myPartialContactBtn modal-footer">
<button type="button" class="btn btn-default visible btnOk" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary visible btnOk" id="btnSave">Enviar</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal -->
}
Any ideas what is wrong?
You get errors on load because you are passing a erroneous Model to the action Email(ContactModel model).
When you ajax post, the Model binder validates the model and adds errors to the model state.
To fix this do as below:
public async Task<ActionResult> Email(ContactModel model)
{
ModelState.Clear();
return PartialView("_Contact", model);
}
Let me know if it helps.

ASP.NET MVC Multiple registration forms submitting issue

I have multiplebutton in one view for now.
For example, Admin and Student.
If I click the Adminbutton, the view will show a popup modal-dialog of the Admin registration form and the same goes to Student.
The following is the code that I written in cshtml:
#using (Html.BeginForm("Register", "Account", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="container">
-- the button | admin --
Admin Modal
<div class="modal fade" id="AdminModal" style="width:auto">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
×
<h3 class="modal-title" >Admin Modal</h3>
</div>
<div class="modal-body">
<form id="AdminForm">
-- with other textfields ---
-- and DropDownList for selecting User role, eg. Admin/Student --
</form>
</div>
<div class="modal-footer">
Cancel
<input type="reset" value="Submit" class="btn btn-success" id="btnSubmit" />
</div>
</div>
</div>
</div>
</div>
<div class="container">
-- the button | student --
Student Modal
<div class="modal fade" id="StudentModal" style="width:auto">
<div class="modal-dialog">--student form content--<div>
</div>
</div>
}
Provided with .Js:
$(document).ready(function () {
$("#btnSubmit").click(function () {
var AdminFormdata = $("#AdminForm").serialize();
$.ajax({
type: "POST",
url: "/Account/Register",
data: AdminFormdata,
success: function (d) {
console.log(d);
$("#AdminModal").modal("hide");
}
})
})
});
I tried with the Admin dialog, the above code does work to popup the particular dialog. However when I click the Submit button, it does not get the appropriate data from the chosen registration form. What is the problem here?
HTML does not allow to nest a <form> inside another <form>. Move the <div class="modal "> outside of the #using(Html.BeginForm) block.
Something like this:
#using (Html.BeginForm("Register", "Account", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary("", new { #class = "text-danger" })
Admin Modal
} #* close main form here! *#
<div class="modal fade" id="AdminModal" style="width:auto">
#* ... *#
<form id="AdminForm"> ... </form>
</div>

How do I rebind the mvc model for a bootstrap modal dialog?

I have an MVC 4 application containing a grid with a link button to trigger the display of record details. I'm using a bootstrap modal dialog to display record details when the user selects a grid row.
I don't want to load the record details unless they are asked for; there are too many data elements involved (1000+).
The grid page uses a modal div containing the partial page (with a ViewModel reference).
I need the partial page's ViewModel to refresh prior to the display of the dialog. so when the user clicks the link, I get the record id from the grid and use it to create the url to the controller method - which seems to work, but seems to happen AFTER the dialog is shown.
How do I get this to work?
This code is in my Index.cshtml:
×
Account Number: #Html.DisplayFor(model => model.AccountNumber)
#{Html.RenderPartial("_KeyTable");}
#{Html.RenderPartial("_LoanTable");}
Close
$(document).ready(function () {
$("#divDialog").hide();
$("#btnClose").hide();
$("#lblAcceptAll").show();
$("#OnHoldsGrid").focus();
pageGrids.OnHoldsGrid.onRowSelect(function (e) {
accountNumber = e.row.AccountNumber;
});
$(".modal-link").click(function (event) {
event.preventDefault();
$('#detailsModal').removeData("modal");
var url = '#(Url.Action("_DetailsForModal", "Home", null, Request.Url.Scheme))?accountNumber=' + accountNumber;
$('#detailsModal').load(url);
$('#detailsModal').modal('show');
//alert(url);
});
});
// This code is in my Controller:
public ActionResult _DetailsForModal(string accountNumber)
{ // This refreshes the data in the ViewModel:
LOIHoldsViewModel model = new LOIHoldsViewModel();
model.GetLOIHoldExtended(accountNumber);
return PartialView("_DetailsForModal", model);
}
// This code is in my partial page _KeyTable.cshtml:
#model LOIHolds.Models.LOIHoldsViewModel
<div id="divKeyTable">
<br />
<hr />
<div class="KeyTableExpandContent">
<h2>Show/Hide Key Table Information</h2>
</div>
<label>Provider Date:</label>
#Html.DisplayFor(model => model.LOIHoldWithTables.KeyTable.ProviderDate)
<label>PFI Date:</label>
#Html.DisplayFor(model => model.LOIHoldWithTables.KeyTable.PFIDate)
<label>User Accept Date:</label>
#Html.DisplayFor(model => model.LOIHoldWithTables.KeyTable.UserAcceptDate)
<label>User Deny Date:</label>
#Html.DisplayFor(model => model.LOIHoldWithTables.KeyTable.UserDenyDate)
<label>Process Date:</label>
#Html.DisplayFor(model => model.LOIHoldWithTables.KeyTable.ProcessDate)
<label>Fiserv Accept Date:</label>
#Html.DisplayFor(model => model.LOIHoldWithTables.KeyTable.FiservAcceptDate)
</div>
<script>
$('.KeyTableExpandContent').click(function () {
$('.divKeyTable').toggle();
});
</script>
// This is the partial _DetailsForModal.cshtml:
#model LOIHolds.Models.LOIHoldsViewModel
<div class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="detailsModalLabel"><label>Account Number: </label>#Html.DisplayFor(model => model.AccountNumber) </h4>
</div>
<div class="modal-body">
<p>
#{Html.RenderPartial("_KeyTable");}
#{Html.RenderPartial("_LoanTable");}
</p>
</div>
<div class="modal-footer">
<button type="button" id="CancelModal" class="btn btn-default modal-close-btn" data-dismiss="modal">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
You will have to use Ajax when you click the .modal-link:
$(".modal-link").click(function (event) {
var mUrl = '#(Url.Action("DetailsForModal", "Home", null, Request.Url.Scheme))?accountNumber=' + accountNumber;
$.ajax({
url: mUrl,
success:function(result){
// result should contain PartialView from Controller
//Assign Modal DIV the PartialView
$('#detailsModal').html(result);
$('#detailsModal').modal('show');
}
});
}
Put your Modal Logic in a Partial View, then Create a function in Home Controller: Something like this:
public ActionResult DetailsForModal(int accountNumber){
var model = new PartialModalDialogViewModel();
// Load Modal Data
return PartialView("PartialViewName", model);
}
EDIT:
Try removing this from the Modal Partial View and put in somewhere in the _Layout.cshtml
<div class="modal fade" id="detailsModal" tabindex="-1" role="dialog" aria-labelledby="detailsModalLabel" aria-hidden="true">
</div>

Categories