MVC - Opening PartialView in a jquery dialog - c#

I have a problem that's been driving me crazy for days. So I have an html table with items in it. The point is basically to click a button and open a jquery dialog with a message, asking me if I want to delete the selected item. Now the delete part can come next cause as it is I can't even display the dialog with the confirmation message. What I do is click one of the delete icons on my table to delete an item of my choosing, but as the partialview with the dialog finishes loading, jquery throws an undefined function error. The following pattern has already been implemented on another similar funcionality (table with clickable icon, shows dialog) but I can't find out whats wrong here.
Here's the code of the table in the "main" view.
<table width="100%" cellspacing="0" border="0" align="center" cellpadding="3"
style='table-layout: fixed'>
<tr class="tr-header">
<th width="20px">
</th>
<th width="200px">
File Name
</th>
<th width="120px">
Type
</th>
<th width="130px">
Date
</th>
<th width="480px">
Comments
</th>
</tr>
#foreach (var item in Model.Uploads)
{
<tr>
<td align="center">
#using (Ajax.BeginForm("DeleteUpload", "Candidate",
new { id = item.UploadID },
new AjaxOptions { UpdateTargetId =
"DeleteUploadForm",
HttpMethod = "Get" }))
{
#*<a href='#Url.Action("DeleteUpload", new { id = item.UploadID })'>
<img src="#Url.Content("~/icons/delete.png")" alt="Click to delete upload" border="0" /></a>*#
<input type="image" name="DeleteUpload" id="DeleteUpload" src="#Url.Icon("delete.png")"/>
}
</td>
<td align="center">
#(item.FileName);
</td>
<td align="center" nowrap="nowrap">
#item.UploadType
</td>
<td align="center" nowrap="nowrap">
#item.UploadDate
</td>
<td align="justify" style="overflow:auto">
#Html.Raw(Html.Encode(item.Comments).Replace("\n", "<br />"))
</td>
</tr>
}
</table>
<div id="DeleteUploadForm">
</div>
As you notice in the first column I have two ways of calling the controller commented, the one with the input image doesn't do a submit when I click it and the anchor link can call the controller and the partialview where I have the dialog, but jQuery library "crashes" when its all done.
This is the controller.
public ActionResult DeleteUpload(int id)
{
Upload UploadToDelete = CandidateProxy.GetUploadByID(this.CurrentUser.DbInfo, id);
return PartialView(UploadToDelete);
}
Nothing too spectacular there. Then it calls the following partial view.
#model Project.Entities.Uploads
<script src="#Url.Script("jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Script("jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="#Url.Script("jquery-ui-1.8.11.min.js")" type="text/javascript"></script>
<script src="#Url.Script("ui/jquery.ui.core.js")" type="text/javascript"></script>
<script src="#Url.Script("ui/jquery.ui.widget.js")" type="text/javascript"></script>
<script src="#Url.Script("ui/jquery-ui-1.8.23.custom.js")" type="text/javascript"></script>
<script src="#Url.Script("ui/jquery.ui.mouse.js")" type="text/javascript"></script>
<script src="#Url.Script("ui/jquery.ui.button.js")" type="text/javascript"></script>
<script src="#Url.Script("ui/jquery.ui.draggable.js")" type="text/javascript"></script>
<script src="#Url.Script("ui/jquery.ui.position.js")" type="text/javascript"></script>
<script src="#Url.Script("ui/jquery.ui.resizable.js")" type="text/javascript"></script>
<script src="#Url.Script("ui/jquery.ui.dialog.js")" type="text/javascript"></script>
<script src="#Url.Script("ui/jquery.effects.core.js")" type="text/javascript"></script>
<script src="#Url.Script("dialog/DeleteUploadDialog.js")" type="text/javascript"></script>
<div="DeleteUploadDialog">
#using (Html.BeginForm("DeleteUpload", "Home", FormMethod.Post))
{
<fieldset>
<div>
<br />
Do you want to delete the following file? #Model.UploadName
</div>
<input type="submit" name="submit" value="Delete" class="toolbar-button" />
<input type="button" name="submit" value="Cancel" class="toolbar-button" />
</fieldset>
}
</div>
This is the partialview that holds the design for my dialog. It will eventually send to the Controller a request to delete an upload which is easy cause I'm more familiar with server-side coding but this whole front-end thing is very new to me. Finally here's the DeleteUploadDialog.js file where I have written the dialog's properties.
$(function () {
$("#DeleteUploadDialog").dialog({
autoOpen: true,
modal: true,
width: 950,
height: 350,
close: function (event, ui) {
$("#DeleteUploadDialog").remove();
}
});
});
So that's my code. Anything else you'd like to know about it let me know. Thanks in advance!

Making a server round trip just for confirmation is not a good idea. you can take confirmation on client side using below custom confirmation dialog. This will not block your script execution also.
I have created custom confirmation box, you may try this:
function ConfirmationBox(pTitle, pText, pButtonType, pParam, pCallBack, pCancelCallback) {
if (pButtonType == null) pButtonType = "okcancel";
$('<div></div>').appendTo('body').html(pText)
.dialog({
resizable: false,
modal: true,
title: pTitle,
buttons: GetButtons(pButtonType),
autoOpen: true,
width: 'auto'
, Close: function (event, ui) {
$(this).remove();
}
});
$("input[type=submit], input[type=button]").button();
$("#confirmDialog button").button();
return this;
function GetButtons(pButtonType) {
var cBtn;
switch (pButtonType) {
case "yesno":
cBtn = {
"Yes": function () {
if (pCallBack && pCallBack.length > 0) {
window[pCallBack](pParam);
}
$(this).dialog("close");
return true;
},
"No": function () {
if (pCancelCallback && pCancelCallback.length > 0) {
window[pCancelCallback](pParam);
}
$(this).dialog("close");
return false;
}
}
break;
case "okcancel":
cBtn = {
"Ok": function () {
if (pCallBack && pCallBack.length > 0) {
window[pCallBack](pParam);
$(this).dialog("close");
}
return true;
},
Cancel: function () {
if (pCancelCallback && pCancelCallback.length > 0) {
window[pCancelCallback](pParam);
$(this).dialog("close");
}
return false;
}
}
break;
}
return cBtn;
}
}
Parameter details:
pTitle: Title of your dialog
pText: Text of dialog
pButtonType: Here we have 2 option yesno | okcancel
pParam: parameter to callback function
pCallBack: Success callback (function to call on "Yes" click)
pCancelCallback: Cancel callback (function to call on "No" click )

I think that what you are trying to do here is an overhead. You are opening a dialog and removing it on close.. Wouldn't be simpler to do sth like this:
$(buttonDelete).click(function () {
var confirmDelete = confirm("Are you sure you want to delete this item?");
if (confirmDelete === true) {
$.ajax({
url: '/Home/DeleteAttachment',
dataType: "json",
type: "POST",
data: { "id": id },
success: function () {
$(rowToDelete).remove();
}
});
}
});
and
[HttpPost]
public JsonResult DeleteAttachment(int id)
{
DeleteAttachment(id);
return Json("ok");
}
if you really want to return partial you can do sth like this:
$(buttonDelete).click(function () {
var confirmDelete = confirm("Are you sure you want to delete this item?");
if (confirmDelete === true) {
$.ajax({
url: '/Home/DeleteAttachment',
dataType: "html",
type: "POST",
data: { "id": id },
success: function (response) {
$(divId).replace(response);
}
});
}
});
and
[HttpPost]
public PartialViewResult DeleteAttachment(int id)
{
Upload UploadToDelete = CandidateProxy.GetUploadByID(this.CurrentUser.DbInfo, id);
return PartialView(UploadToDelete);
}

Shouldn't it be
autoOpen: false
instead of
autoOpen: true
Then in your click event something like
$("#DeleteUpload").click(function()
{
$("#DeleteUploadDialog").dialog("open");
});

Related

Why do `JQuery` tabs lose styling after a button click

I am using JQuery tabs in my Asp.Net/C# app.
I am modelling my approach after this article. The JQuery is outside of my
<asp:UpdatePanel ID="UpdatePanel1"...></asp:UpdatePanel>
wrapper while the html components are inside.
Whenever I click a button, my tabs completely lose their CSS styling and I see all of the tab contents, rather than just the
<div id="current-tab">
for that tab.
Why is this happening and how do I fix it?
My guess is that its related to post-back or the update panel somehow, but I am not sure why the added C# code under page_load doesn't keep the selected tab current on post-back when the button is fired.
ASPX
<link href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.9/themes/start/jquery-ui.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.9/jquery-ui.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
var tabs = $("#tabs").tabs({
activate: function (e, i) {
selected_tab = i.index;
}
});
selected_tab = $("[id$=selected_tab]").val() != "" ? parseInt($("[id$=selected_tab]").val()) : 0;
tabs.tabs('select', selected_tab);
$("form").submit(function () {
$("[id$=selected_tab]").val(selected_tab);
});
...
</script>
....
<table>
<tr>
<td style="padding: 5px;">
<div id="tabs">
<ul>
<li>Tier 1</li>
<li>Tier 2</li>
<li>Tier 3</li>
<li>Tier 4</li>
</ul>
<div class="tab-content">
<div id="tab-1">
...
</div>
<div id="tab-2">
...
</div>
<div id="tab-3">
...
</div>
<div id="tab-4">
...
</div>
</div>
</div>
<asp:HiddenField ID="selected_tab" runat="server" />
</td>
</tr>
</table>
C#
protected void Page_Load(object sender, EventArgs e)
{
...
selected_tab.Value = Request.Form[selected_tab.UniqueID];
...
}
You are right, it has something to do with a Partial PostBack. So in order for jquery functions to work again you need to rebind it after the Partial PostBack is done.
<script type="text/javascript">
$(document).ready(function () {
buildTabs();
});
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function () {
buildTabs();
});
function buildTabs() {
var tabs = $("#tabs").tabs({
activate: function (e, i) {
selected_tab = i.index;
}
});
selected_tab = $("[id$=selected_tab]").val() != "" ? parseInt($("[id$=selected_tab]").val()) : 0;
tabs.tabs('select', selected_tab);
$("form").submit(function () {
$("[id$=selected_tab]").val(selected_tab);
});
}
</script>
But the selected tab is a different story. You also need to store the active tab somewhere and re-apply it after the partial PostBack is done. See this answer for details.
But basically you need to store the active tab ID in SessionStorage, cookie or Hiddden input and re-apply it in prm.add_endRequest(function () {

Cant get the right tablerow in my table, to my data propertie in my ajax call

I have this code. My problem is to delete the right row on my table. As you can se on the html every table row have a delete button. How can i in my ajax call in the data propertie get the right table row of based on which delete button i choose to press. right now i have tried this in the data propertie
("id=" + $(this).attr("Id"))
But it dosent work. Do anybody have a better ide?
//My Html
#foreach (var discount in Model.DiscountList)
{
<tr>
<td>#Html.TextBox("codeTextBox", discount.Code) </td>
<td><input type="checkbox" name="freeShippingCheckBox" id="freeShippingCheckBox" checked="#discount.FreeShipping" /> </td>
<td><input type="checkbox" id="activeCheckBox" name="activeCheckBox" checked="#discount.Active" /></td>
<td><input type="datetime" value="#discount.CreatedDate" readonly /></td>
<td>
<input type="button" value="Delete" class="fa fa-remove" />
</td>
<input id="#discount.Id.ToString()" type="hidden" value="#discount.Id" />
</tr>
}
//my jquery/ajax
#section scripts{
<script type="text/javascript">
$(document).ready(function () {
$(".fa-remove").on("click", function () {
if (confirm("Are you sure you want to delete this discount code?")) {
$.ajax({
url: '#Url.Action("DeleteDiscountCode","Discount")',
type: "POST",
data: "id=" + $(this).attr("Id"),
success: function (data) {
if (data) {
alert("Deleted");
}
location.reload();
}
});
}
});
});
</script>
}
//my controller
namespace Web.Controllers
{
public class DiscountController : BaseController
{
[HttpPost]
public void DeleteUser(string id)
{
}
}
}
You can use the jQuery closest() method to get the table row in which your delete button is
$(".fa-remove").on("click", function (e) {
e.preventDefault();
var currentRow = $(this).closest("tr");
//do your ajax call now
});
currentRow is a jQuery wrapped object. So you can call the relevant jQuery methods needed. For example, You probably want to remove the tr in your ajax call's success event
success: function (data) {
if (data) {
alert("Deleted");
currentRow.remove();
}
You might also make use the Url.Action helper method to generate the correct url to your delete action method instead of hardcoding that in javascript code.
<input type="button"
data-url="#Url.Action("DeleteDiscountCode","Discount",new { id= discount.Id})"
value="Delete" class="fa fa-remove" />
Now when user click,simply get the data-url value and use that for the ajax call.
So the full code will be
$(".fa-remove").on("click", function (e) {
e.preventDefault();
var currentRow = $(this).closest("tr");
if (confirm("Are you sure you want to delete this discount code?")) {
$.post($(this).data("url"),function(data){
if (data.status==="success") {
alert("Deleted");
currentRow.remove();
}
else
{
alert("expected truthy! but got something else");
}
});
}
});
Assuming your DeleteDiscountCode accepts an id
[HttpPost]
public ActionResult DeleteDiscountCode(int id)
{
return Json(new { status="success"});
}

Jquery ui Dialog in an MVC listing table

I have a listing table displaying some information from the database.
What i am trying to do is to check if the item status is 1 and if comments exists to display a little icon where the user will click on it and see the specific comment for that item.
So in the listing table it seems to display fine that icon according to the above criteria but when i click on a specific listing it opens all dialogs with comments for all other listings with the same item status instead of the one i have chosen.
Can you please help me on what am i doing wrong ?
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.BookingId)
</td>
<td>
<a href="#Url.Action("ItemDetails", new {id=item.ItemId })" title="#item.Item.ItemDescription">
#Html.DisplayFor(modelItem => item.Item.ItemName)
</a>
</td>
<td>
#Html.DisplayFor(modelItem => item.StartDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.EndDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.RequestDate)
</td>
#if (item.StatusCodeId == 1)
{
<td style="color:#DD7500">
#Html.DisplayFor(modelItem => item.StatusCode.StatusCodeName)
#if (item.Comments != null)
{
<img class="orangeclicker" style="margin-left:3px;display:inline;margin-bottom:-3px;cursor: pointer;" title="Tutor Comments" src="~/Images/chat_icon.gif" />
<div class="orangedialog" title="Tutor Comments">
<p> #item.Comments</p>
</div>
}
</td>
}
}
</tr>
}
</table>
<script> $(function ()
{
$(" .orangedialog").dialog({
autoOpen: false,
show: { effect: "blind", duration: 1000 },
hide: { effect: "explode", duration: 1000 },
buttons: {
Close: function () {
$(this).dialog("close");
}
}
});
$('.orangeclicker').live("click", function () {
$(".orangedialog").dialog("open");
});
});
</script>
You should try this:
first;you have to create links in each row of table having same class.
<a class="comments">Comments</a>
second; update your page as:
<div id="dialog-details" style="display: none">
<p>
#if (item.Comments != null)
{
<img class="orangeclicker" style="margin-left:3px;display:inline;margin-bottom:-3px;cursor: pointer;" title="Tutor Comments" src="~/Images/chat_icon.gif" />
<div class="orangedialog" title="Tutor Comments">
<p> #item.Comments</p>
</div>
}
</p>
</div>
third update your script as:
$('.comments').click(function () {
$("#dialog-details").dialog('open');
return false;
});
$("#dialog-details").dialog({
autoOpen: false,
resizable: false,
height: 170,
width: 350,
show: { effect: 'drop', direction: "up" },
modal: true,
draggable: true,
open: function (event, ui) {
$(".ui-dialog-titlebar-close").hide();
},
buttons: {
"Close": function () {
$(this).dialog("close");
}
}
});
</script>
They all have the same id or class ( because they are render in a foreach statement )
You can add a difference by combining the class or the id with the index from your list
I don't have the code in front of me, but I also think something like this would work.
UPDATE:
$('.orangeclicker').live("click", function (e) {
alert("check"); // if this fires at click, the problem is somewhere else
var target= $(e.currentTarget);
target.next().dialog("open");
});
You should Use $(this).next().next().find(".orangedialog") to find relevent element.
$('.orangeclicker').on("click", function (e) {
$element = $(this).next().next().find(".orangedialog");
$element.dialog("open");
});
Update
Use on() instead of live()
See DEMO

Javascript function is not working on asp:button Click event, where a test alert function works.!

I am trying to create an alert as described in this site http://needim.github.com/noty/
and here is the code
<head runat="server">
<title>Test</title>
<script src="jquery-1.7.2.min.js" type="text/javascript"></script>
<script type="text/javascript" src="js/noty/jquery.noty.js"></script>
<script type="text/javascript" src="js/noty/layouts/top.js"></script>
<link rel="stylesheet" type="text/css" href="buttons.css" />
<script type="text/javascript" src="js/noty/themes/default.js"></script>
</head>
<body>
<div class="container">
<div id="customContainer">
</div>
</div>
<script type="text/javascript">
function generate(type, layout) {
var n = noty({
theme: 'defaultTheme',
text: 'Do you want to continue?',
buttons: [
{
addClass: 'btn btn-primary',
text: 'Ok',
onClick: function ($noty) {
// this = button element
// $noty = $noty element
$noty.close();
noty(
{
text: 'Record deleted !',
type: 'success',
callback:
{
onShow: function () { },
afterShow: function () { TakeValue(true); },
onClose: function () { },
afterClose: function () { }
}
});
}
},
{
addClass: 'btn btn-danger',
text: 'Cancel',
onClick: function ($noty) {
$noty.close();
noty(
{
text: 'Record not deleted !',
type: 'warning',
callback:
{
onShow: function () { },
afterShow: function () { TakeValue(false); },
onClose: function () { },
afterClose: function () { }
}
});
}
}
]
});
}
function TakeValue(result) {
if (result == true) {
document.getElementById("Hidden1").value = "true";
alert(document.getElementById("Hidden1").value);
} else {
document.getElementById("Hidden1").value = "false";
alert(document.getElementById("Hidden1").value);
}
}
function generateAll() {
generate('information', 'top');
}
</script>
<form id="form" runat="server">
<input id="Hidden1" type="hidden" value="false"/>
<asp:Button ID="Button2" runat="server" Text="Press" OnClientClick="return generateAll();" />
<input id="Button1" type="button" value="button" onclick="return generateAll();" />
</form>
</body>
I have placed two buttons ,one is HTML button while the other is of asp:Button,
The whole scenario just works fine when I use the HTML button ,but the page is not displaying the similar behavior in case of asp:Button click, I have placed a test function in JavaScript to test the OnClientClick event of the asp:Button and that worked fine,but I don't know why this alert is not getting called, I think there is some problem with the Noty JS.
Kindly give feed back
thanks.
As jbabey said in the comments:
an asp:button will cause a postback when clicked by default. you need to return false from the onclientclick, right now you are returning undefined since generateAll has no return.
Since you're using jQuery, I'd go one step further and not directly set the click attribute. Instead, set it using jQuery:
<script>
$(document).ready(function() {
$('#Button1').click(generateAll);
});
...
function generateAll(e) {
generate('information', 'top');
// This will prevent the default action of submitting the form.
e.preventDefault();
}
</script>
Could you please add UseSubmitBehavior="false" attribute to the asp:button.
<asp:Button ID="Button2" runat="server" Text="Press" UseSubmitBehavior="false" OnClientClick="return generateAll();" />
I hope this will resolve your issue. Please let me know whether it helped you or not.

data not displaying on form on ajax success

I am trying a simple task of displaying student name in a textbox based on StudentId entered. I am able to display the student name as an alert from jQuery - AJAX call but not in the text box, what am I missing here?
Controller:
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult DisplayStudentName(string id)
{
StudentDataContext db = new StudentDataContext();
var StudentName = (from p in db.vwStudents.Where(a => a.StudentNumber == id)
group p by p.StudentName into g
select g.Key).FirstOrDefault();
return Json(new { Name = StudentName });
}
jQuery:
$(function () {
$('#submitButton').click(function () {
var link = '/StudentForm/DisplayStudentName';
$.ajax({
type: 'POST',
url: link,
data: { id: $('#id').val() },
dataType: 'json',
success: function (result) {
$("#StudentName").val(result.Name);
alert(result.Name);
},
error: function (result) {
alert("Failed")
}
});
});
});
View:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Student Form
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<div id="Data" style="text-align: left; height: 202px;">
Student Number:<input type="text" name="id" id="id"/><br />
Student Name:<input type="text" name="StudentName" id="StudentName"/><br />
<br />
<div id="Div1">
<button id="submitButton" name="submitButton" style="width:140px;">Display Short Name</button>
</div>
</div>
</asp:Content>
Again, I am able to display Student Name in the Alert window, but not in the text box, Am I missing something?
Thanks in advance
You need to prevent the default behavior of submit button. You can use the jQuery preventDefault function to do this,
$(function () {
$('#submitButton').click(function (e) {
e.preventDefault(); //prevent default behaviour
var link = '/StudentForm/DisplayStudentName';
$.ajax({
type: 'POST',
url: link,
data: { id: $('#id').val() },
dataType: 'json',
success: function (result) {
$("#StudentName").val(result.Name);
},
error: function (result) {
alert("Failed")
}
});
});
})
When preventDefault method is called, the default action of the event will not be triggered. So in this case the form submission will not happen ( so the page wont be reloaded).

Categories

Resources