MVC4, Render Partial View in Dialog Box with jQuery, How to refresh - javascript

I have a partial view that is popping up in a dialog with the code below. However, after the user saves the partial view the data does not refresh in that partial view when I click the ActionLink again until I stop debugging and restart the app. However, the new record is in my databsae. The other issue is when I restart the app I cannot update the record because of the error below. What am I missing? Thanks.
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
The div tag in my View
<div id="assign-dialog"></div>
The ActionLink in the same view
#Html.ActionLink("Assign", "Edit", "Assignment", new { id = Model.InfoId}, new { #class = "assign-modal" })
The jQuery
$(function () {
$(function () {
$('#assign-dialog').dialog({
autoOpen: false,
width: 400,
height: 500,
resizable: true,
modal: true
});
$('.assign-modal').click(function () {
$('#assign-dialog').load(this.href, function () {
$(this).dialog('open');
});
return false;
});
});
The HTTP GET action
[HttpGet]
[Authorize(Roles="Admin")]
public ActionResult ViewAssignment(int id = 0)
{
RequestAssignment query = _assignmentRepository.GetCurrentAssignment(id);
return PartialView("_ViewAssignment", query)
}
UPDATE:
I originally followed the steps in javascript/jquery modal popup dialog MVC 4 / render partial view under the dynamic section of Jasen's answer, but did not know what to put in the "Client Partial, empty for now "
...okay so going off some other posts I have read this is what I was able to come up with, but nothing happens when I click my link.
View html
Assign
<div id="assign-modal">
</div>
jQuery
//Dialog Box for Assignments
$(".dialog-trigger").on("click", function(event) {
event.preventDefault();
var infoId= $(this).data("infoId");
$.ajax({
url: "RequestAssignment/Edit/" + infoId,
type: "GET"
})
.done(function(result) {
$("#assign-modal").html(result).dialog("open");
});
});

so after some long searching, I decided to use Ajax.ActionLink. I know there are better ways out there, but this one was working for me. I want to thank #MattBodily for all the help along the way.
#Ajax.ActionLink("Approve", "QuickAssign", "Assignment", new { id = Model.InfoId}, new AjaxOptions { HttpMethod = "GET", UpdateTargetId = "result", InsertionMode = InsertionMode.Replace, OnSuccess = "openDialog" })
then my javascript function
function openDialog() {
//set the diaglog properties
$("#result").dialog({
title: 'Assign',
width: 550,
height: 'auto',
modal: true
});
$("#result").dialog("open");
}

Related

$.when(ajaxCall) Versus success

I have the following code inside my asp.net MVC view:-
$('body').on("click", "#transferserver,#transfersd,#transferfirewall,#transferrouter,#transferswitch", function () {
$("#showoptions").dialog({
title: "Assign Selected Records To New Rack",
width: 'auto', // overcomes width:'auto' and maxWidth bug
maxWidth: 600,
height: 'auto',
modal: true,
fluid: true, //new option
resizable: false
});
var ajaxCall = $.ajax({
url: '#Url.Content("~/Rack/ShowTransferSelectedDialog")',
data: {
rackfrom: "#Model.Rack.ITsysRackID",
assettype: $(this).attr('id')//get the id for the clciked link, so that the submit button will call the associted action method.
},
type: 'get',
success: function (html) {
$('#showoptions').html(html);
$("#showoptions").dialog("show"); //This could also be dialog("open") depending on the version of jquery ui.
}
});
$.when(ajaxCall)
.then(function (data) { showDialog(data); });
});
I have the following questions:
What are the differences between the $when(ajaxcall) and on success ?
In my above code if I remove the $.when(ajaxCall) the dialog box will still be displayed . so is there any need to have it?
Thanks
EDIT
But one benefit i find for using $.when(ajaxCall) is that i have defined a custom authorization attribute as follow:-
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CheckUserPermissionsAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
var viewResult = new JsonResult();
viewResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
viewResult.Data = (new { IsSuccess = "Unauthorized", description = "Sorry, you do not have the required permission to perform this action." });
filterContext.Result = viewResult;
}
}
}
currently if the user clicks on the link to display the dialog box and he is not authorize to do so , he will receive a jAlert containing the unauthorized message as follow:-
![enter image description here][1]
but if i remove the $.when(ajaxCall), then the user will not receive the unauthorization message , and instead the dialog will be blank .. so can anyone advice ?
1) This is the definition of jQuery when
Provides a way to execute callback functions based on one or more objects, usually Deferred objects that represent asynchronous events.
It make no sense to use it for a single ajax call, you want to use it for 2 or more so you wait for them to finish before executing some code.
2) I don't know what showDialog does but your dialog already shows because in your success handler you have $("#showoptions").dialog("show");. Again, no need at all to use when here

Kendo UI Window widget - Dynamic title using templates

Is it possible to have dynamic window titles using templates?
Something like this:
wnd = $("#details").kendoWindow({
title: #= ItemName #,
modal: true,
visible: false,
resizable: false,
width: 300}).data("kendoWindow");
I added ItemName in the title field merely to indicate the concept. Any idea?
You can do it with setOptions api method, something like:
// Setting some options
wnd.setOptions({
title: "dynamic title",
width: "60%"
});
First initialize your window with your code and on some events (button click may be), use window object to set its options.
If its not clear, lets play with example: I am setting the window title on kendo-grid custom command button click:
<div class="k-content">
<div id="noteswindow"></div>
</div>
<script>
$(document).ready(function () {
$("#noteswindow")
.kendoWindow({
actions: ["Refresh", "Maximize", "Minimize", "Close"],
visible: false
})
});
function onNotesClick(e) { // Custom button click
e.preventDefault();
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
rData = dataItem;
// Using same window variable again and again for successive clicks with dynamic content
var nWin = $("#noteswindow").data("kendoWindow");
// Setting some options
nWin.setOptions({
title: "Notes on " + dataItem.AssetOrShotName,
width: "60%"
});
nWin.refresh({
url: "../Task/Notes",
data: { AssignId: rData.Id }
});
nWin.open().center();
}
</script>
This is easy way i have show event title in title header like that
API.get('/Scheduler/GetEventDetailById', detailParams).then(function (data) {
$('.k-window-title').text(data.EventTitle);
});

trigger an jQuery UI Dialog if user not authorized

On my website I have two ways to login. The first is used then an user is pushing the Logon button, which trigger an jQuery UI Dialog to open. The second is an normal view, which is used, if an user isn't Authorized, which redirect to an normal login view. But what i liked to do instead, is if an user is not Authorized, it opens the Login jquery ui dialog instead of redirection to the view the user is intended.
This is how i currently are opening the dialog,
$(".openLoginDialog").on("click", function (e) {
e.preventDefault();
$("<div></div>")
.addClass("dialog")
.attr("id", $(this).attr("data-dialog-id"))
.appendTo("body")
.dialog({
title: $(this).attr("data-dialog-title"),
create: function (event, ui) {},
close: function () { $(this).remove() },
open: function (event, ui) {},
modal: true,
position: ['center', 130],
minWidth: 510,
resizable: true,
zIndex: 20000
})
.load(this.href);
});
Because the content in the dialog is an partialView it's called like this:
<div class="items iconlogin highligth-br"><a class="openLoginDialog" data-dialog-id="LoginDialog" data-dialog-title="Login" href="#Url.Action("LogOn", "Authentication", new { returnUrl = Request.Url.ToString() })">Login</a></div>
Also to help me controlling the not Authorized, i have overriden this calls.
public override void OnAuthorization(AuthorizationContext filterContext)
{
filterContext.Result = new RedirectToRouteResult(new
RouteValueDictionary(new { controller = "Authentication", action = "AccessDenied" }));
}
Last resort would be to redirect to an access denied page, with just an white background, which opens on load, a dialog.
I have a MVC intranet solution that employs functionality similar to what you describing, however it is using windows auth not forms.
Basically I have something like this in the Index...
var userExists = "#ViewBag.User";
// require the user to register if they are not found
if (userExists == "") {
$.get('Home/Register/', function (data) {
$("#Register").html(data);
$("#Register").dialog({
resizable: false,
closeOnEscape: false,
dialogClass: 'no-close',
typeDelay: 250
});
});
}
And then in the controller I just set 'ViewBag.User' to the username if they exist.
Have a look at this example:
http://jqueryui.com/dialog/#modal-form
Notice the autoOpen: false
I'm not familiar with asp.net so I wont be able to help with actual implementation. One approach would be to check where the request came from and if the user is not authorized redirect them back to that page and hit them with a dialog.
Another approach would be to know if the user is authenticated on the page load and override links that require authentication
$(".authRequired").on("click", function (e) {
e.preventDefault();
//fancy logic here to load form and dialog
});

Get data from the server and display in the Edit Form

This question is continuation of the following question Add JSON data to the view that unfortunately ended up unresolved yet.
In my main view which has a form with 2 controls and placeholder for flexigrid I added the following at the bottom
<div id="add-edit-dialog" style="display: none" title="Add / Edit Client">
#Html.Partial("_ClientForm", Model)
</div>
The flexigrid pluglin instantiates in run-time and adds 3 buttons: Add, Edit, Delete.
For Edit button I need to get the current row information from the server and then display it in the Form. For Add button I do not need to go to the server (I think).
This is my current code for the Edit button:
function edit(com, grid) {
$('.trSelected', grid).each(function () {
var id = $(this).attr('id');
id = id.substring(id.lastIndexOf('row') + 3);
currentId = id;
$('#fntype').val('Edit');
var ClientName;
ClientName =$('.trSelected td:eq(2)').text();
var url = '/Client/Edit/' + id ;
$.getJSON(url, function (html) {
// setFormControls(data.Id, data.Role, data.Location, data.JobType,
// data.Description);
// alert(data);
$($dlg).html(html);
});
//location.replace(url);
RunModalDialog("Edit Client: " + ClientName);
});
So, it is going to Edit controller action and returns that same partial view _ClientForm with correct information passed as a model. If I look at the response result returned in FireBug I can see that the returned HTML is correct and all the textboxes have correct information in their values.
However, the dialog that opens looks exactly the same as the dialog for the Add button - in other words, all form controls come blank. I can not figure out what is wrong and why it is not working the way I want it.
This is what I have for the RunModalDialog:
var validator = $("#add-edit-form").validate();
var $dlg = $("#add-edit-dialog").dialog({
autoOpen: false,
show: "blind",
closeOnEscape: true,
resizable: true,
width: 1200,
height: 750,
minHeight: 600,
minWidth: 950,
buttons: {
"Save": function () {
if ($("#add-edit-form").valid()) {
// jobPost.setVals(txtId.val(), txtRole.val(),
// txtLocation.val(), txtJobType.val(),
// txtDescription.val());
$.ajax({
type: 'POST',
//data: JSON.stringify(clientInformation),
url: '/Client/Save',
dataType: 'json',
contentType: 'application/json',
success: function (result) {
// insert new list into grid
$('#flexClients').flexAddData(result);
}
});
$(this).dialog('close');
} else return false;
},
Cancel: function () {
$(this).dialog("close");
clearForm();
if (validator)
validator.resetForm();
}
},
close: function () {
clearForm();
},
open: function () {
//$("#add-edit-dialog").parent().appendTo($("#add-edit-form"));
}
});
function RunModalDialog(title, url) {
if (title) {
$dlg.dialog("option", {"title": title });
}
if (url) {
$dlg.load(url).dialog("option", { "title": title }).dialog("open");
//$dlg.load(url, function () {
// var validator = $("#sform").validate();
// if (validator)
// validator.resetForm();
// $dlg.dialog("option", { "title": title }).dialog("open");
//});
} else {
$dlg.dialog("open");
}
}
The code with the load (and commented code) was another attempt to solve this problem. That sort of worked (the form displayed with the info), but the main Client view was also reloaded so I was seeing double grid.
Do you see what should I change in my code to get this thing working?
Thanks a lot in advance.
With Jazzen Chen from MS help we solved this problem. All I needed to do to display the data correctly was to change getJSON to just get jquery function. Now my form comes with data populated correctly and the next challenge will be to save the data.
I posted a blog post with what I have so far - hope it may help
http://blogs.lessthandot.com/index.php/WebDev/UIDevelopment/AJAX/asp-net-mvc-project-with

Passing control values to partial view rendered in a popup with Asp.net MVC3

I have created a popup to load a partial view. I want to pass control values from the parent page to the partial view rendered in the popup. How can I pass the values?
Below is the the code used to open the popup. ModifyAgRule is the div id and AuthorityGridModify is the name of action method used to render the partial view.
Some more info:
I have a webgrid in the parent page, when the user selects one row in this grid and clicks on the modify button a popup should appear with the selected values present in dropdowns and textboxes.
<script type="text/javascript">
$(document).ready(function () {
//define config object
var dialogOpts = {
title: "Modify Rule",
modal: true,
autoOpen: false,
height: 500,
width: 500,
open: function () {
//display correct dialog content
$("#ModifyAgRule").load("AuthorityGridModify");
}
};
$("#ModifyAgRule").dialog(dialogOpts); //end dialog
$('#Modify').click(function () {
$("#ModifyAgRule").dialog("open");
return false;
});
});
</script>
You can pass data to your view in JSon format like this
$("#ModifyAgRule").load('#Url.Action("AuthorityGridModify")',
{ 'propertyName' : 'propertyValue',
'propertyName2' : 123 });
in your controller
public ActionResult AuthorityGridModify(string propertyName, int propertyName2)
{
// propertyName´s value is propertyValue
return View();
}
hope this helps!

Categories