I am writing a MVC3 project. Right now I have a table which has column with Data as actionLinks as:
<td style="color: Black; background-color: Bisque; text-align: center; width: 410px">
#Html.ActionLink(#item.LookUp_NameString, "EditPartial", "Capitation", new { id = item.CAPITATION_RATE_ID }, new { #class = "actionLink" })
</td>
EditPartial as the name suggests is a partial view, which I need to be opened as a pop-up menu so that user can edit the details of the object, save it and we can come back to original page.
I have tried the render partial, but can't get it to pass the id value dynamically.
This is for edit functionality of my grid. What will be the best way to implement this?
If you want to open the result of EditPartial Action method in a model popup, you need some model popup code for that.
jQuery UI is one option. http://jqueryui.com/demos/dialog/
1) Include jQuery UI reference in your page,
2) Add the below script to your page which will convert your normal link to a model popup
<script type="text/javascript">
$(function(){
$(".actionLink").click(function (e) {
var url = this.href;
var dialog = $("#dialog");
if ($("#dialog").length == 0) {
dialog = $('<div id="dialog" style="display:hidden"></div>').appendTo('body');
}
dialog.load(
url,
{}, // omit this param object to issue a GET request instead a POST request, otherwise you may provide post parameters within the object
function (responseText, textStatus, XMLHttpRequest) {
dialog.dialog({
close: function (event, ui) {
dialog.remove();
},
modal: true,
width: 460, resizable: false
});
}
);
return false;
});
});
</script>
From your action result, you can return whatever markup you want to show in the Model popup. Mostly you will be returning a View. If you want to show a partial View,If it is an ajax request and show the normal view if it is a normal request, you can check the Request.IsAjaxRequest method to do that.
public ActionResult EditPartial(int id)
{
CustomerViewModel objCustomer=GetCustomer(id);
if(Request.IsAjaxRequest())
{
return View("Partial/Edit",objCustomer);
}
return View(objCustomer);
}
Assuming you have 2 views present to show your normal page and partial page (for model popup)
I prefer to name my action method as Edit instead of EditPartial, because it is handling both requests (ajax and normal)
Related
I have a situation where I am wanting to observe the behavior of a view model as I am populating a form. I can do this with defining a lot of fields that look kind of like the model, and binding to them, but that is kind of messy.
I am currently accomplishing this with the following code;
(function ($) {
$.printJSON = function(value){
return JSON.stringify(value, undefined, 2);
}
})(jQuery);
var viewModel = kendo.observable({
// other fields etc
update: function (e) {
e.preventDefault();
$("#json_result").html($.printJSON(this));
}
});
<div style="width: 400px; float: left; padding-left: 15px;" >
<button data-bind="click: update" value="Update" >Update</button>
<pre id="json_result">
</pre>
</div>
So you click the button, and it runs the function to draw the view model JSON to the screen, all nice and formatted.
But this still requires a button click. While that isn't that big of a problem for me, since this isn't something I need for a lot of situations, is there any way to actually do this and have it update when the view model changes in any way? I tried to just bind to the function and it never updates without an explicit call, I tried binding right to the view model, and that didn't work either.
You could either simply bind the change event:
viewModel.bind("change", function (e) {
$("#json_result").html($.printJSON(this));
});
or you could use a calculated field:
var viewModel = kendo.observable({
field1: "field1",
field2: "field2",
field3: "field3",
print: function () {
// need to register for all fields so that the change event for print is triggered
for (var fieldName in this) {
if (this.hasOwnProperty(fieldName)) {
this.get(fieldName);
}
}
return $.printJSON(this.toJSON());
}
});
and bind to it with:
<pre data-bind="html: print">
See fiddle demonstrating both methods: http://jsfiddle.net/lhoeppner/S2WeB/
There is a new Tooltip Widget in jQuery UI 1.9, whose API docs hint that AJAX content can be displayed in it, but without any further details. I guess I can accomplish something like that with a synchronous and blocking request, but this isn't what I want.
How do I make it display any content that was retrieved with an asynchronous AJAX request?
Here is a ajax example of jqueryui tootip widget from my blog.hope it helps.
$(document).tooltip({
items:'.tooltip',
tooltipClass:'preview-tip',
position: { my: "left+15 top", at: "right center" },
content:function(callback) {
$.get('preview.php', {
id:id
}, function(data) {
callback(data); //**call the callback function to return the value**
});
},
});
This isn't a complete solution obviously, but it shows the basic technique of getting data dynamically during the open event:
$('#tippy').tooltip({
content: '... waiting on ajax ...',
open: function(evt, ui) {
var elem = $(this);
$.ajax('/echo/html').always(function() {
elem.tooltip('option', 'content', 'Ajax call complete');
});
}
});
See the Fiddle
One thing to lookout for when using the tooltip "content" option to "AJAX" the text into the tooltip, is that the text retrieval introduces a delay into the tooltip initialization.
In the event that the mouse moves quickly across the tooltip-ed dom node, the mouse-out event may occur before the initialization has completed, in which case the tooltip isn't yet listening for the event.
The result is that the tooltip is displayed and does not close until the mouse is moved back over the node and out again.
Whilst it incurs some network overhead that may not be required, consider retrieving tooltip text prior to configuring the tooltip.
In my application, I use my own jquery extensions to make the AJAX call, parse the resutls and initialise ALL tooltips, obviously you can use jquery and/or your own extensions but the gist of it is:
Use image tags as tooltip anchors, the text to be retrieved is identified by the name atrribute:
<img class="tooltipclassname" name="tooltipIdentifier" />
Use invoke extension method to configure all tooltips:
$(".tooltipclassname").extension("tooltip");
Inside the extension's tooltip method:
var ids = "";
var nodes = this;
// Collect all tooltip identifiers into a comma separated string
this.each(function() {
ids = ids + $(this).attr("name") + ",";
});
// Use extension method to call server
$().extension("invoke",
{
// Model and method identify a server class/method to retrieve the tip texts
"model": "ToolTips",
"method": "Get",
// Send tooltipIds parameter
"parms": [ new myParmClass("tipIds", ids ) ],
// Function to call on success. data is a JSON object that my extension builds
// from the server's response
"successFn": function(msg, data) {
$(nodes).each(function(){
// Configure each tooltip:
// - set image source
// - set image title (getstring is my extension method to pull a string from the JSON object, remember that the image's name attribute identifies the text)
// - initialise the tooltip
$(this).attr("src", "images/tooltip.png")
.prop("title", $(data).extension("getstring", $(this).attr("name")))
.tooltip();
});
},
"errorFn": function(msg, data) {
// Do stuff
}
});
// Return the jquery object
return this;
Here is an example that uses the jsfiddle "/echo/html/" AJAX call with a jQuery UI tooltip.
HTML:
<body>
<input id="tooltip" title="tooltip here" value="place mouse here">
</body>
JavaScript:
// (1) Define HTML string to be echo'ed by dummy AJAX API
var html_data = "<b>I am a tooltip</b>";
// (2) Attach tooltip functionality to element with id == tooltip
// (3) Bind results of AJAX call to the tooltip
// (4) Specify items: "*" because only the element with id == tooltip will be matched
$( "#tooltip" ).tooltip({
content: function( response ) {
$.ajax({
url: "/echo/html/",
data: {
'html': html_data
},
type: "POST"
})
.then(function( data ) {
response( data );
});
},
items: "*"
});
here is this example on jsfiddle:
Apologies in advance if this becomes a very long question...
Background Info
I have an MVC 3 application, using Telerik components and this particular issue is specific (I think) to the Window() component.
From my main view (Index.cshtml) I executing an ajax request to return a partial view which is what I am populating the contents of my window with. This is the jquery which is executing the request:
var url = '#Url.Action("GetAddPart", "Jobs")';
var window = $("#Window").data("tWindow");
var data = $("#indexForm").serialize();
window.ajaxRequest(url, data);
window.center().open();
the controller action is:
[HttpGet]
public ActionResult GetAddPart(MDTCompletedJobM model)
{
// show the AddPart window
//TryUpdateModel<MDTCompletedJobM>(model);
model.ActionTakenList = ActionTakenList;
model.ProblemTypes = ActualProblemList;
var addPartM = new MDTAddPartM() { CompletedJobM = model };
return PartialView(string.Concat(ViewDefaultUrl, "AddPart.cshtml"), addPartM);
}
this opens my window hunky dory.
in my partial view i have a form with two or three fields and an "Add", "Cancel button. For the sake of brevity I'll just show what I think are the relevant parts of the partial view, but i can produce the entire view if need be:
<div id="resultDiv">
#using (Html.BeginForm("AddPart", "Jobs", FormMethod.Post, new { id = "addPartForm", name = "addPartForm" }))
{
** layout components removed from here **
<input type="button" value="Add" class="t-button" id="btnAdd"/>
<input type="button" value="Cancel" class="t-button" id="btnCancel"/>
<p />
<div id="progressdiv">
</div>
}
</div>
is the "top level" tag in the partial view.
my jquery to handle the Cancel button is:
$("#btnCancel").click(function () {
var window = $("#Window").data("tWindow");
window.close();
});
In my main view, I have a submit button, which when completed effectively reders the main view "disabled" or displays errors. The action for this submit button returns the main view:
Controller's action snippet:
if (ViewData["DoPayJobWarningStr"] == null)
return RedirectToAction("GetAutoDispatchJob", new { autoDispatchJob = model.JobReferenceNumber});
else
return View(string.Concat(ViewDefaultUrl, "Index.cshtml"), tmpModel);
My actual problem
For a specific example I am using, I am expecting ViewData["DoPayJobWarningStr"] NOT to be null, there the return View(...) will be executed.
if I execute this action (for the submit button) without opening the window, my view returns correctly and the page is updated to show the warning message. However, if I open the window first then execute the submit button, the View isn't updated on the page, but seems to be placed into the Window's html. ie, if I hit the submit button (nothing happens), then click on the button which opens the Telerik window, I briefly see the View returned by the submit Action being shown before it's updated with what the Partial View should contain. I don't understand at all how or why the returned View is being placed there?
Things I've tried:
Commenting out the ajax request (window.ajaxRequest(url, data);) fixes the issue (even though I obviously have a blank partial view to look at).
Not making the Partial View a "Form" doesnt' work
No matter how I "close" the window, the view is still placed within there. eg clicking the x in the top right hand corner
Using Firebug, the HTML after the submit button is clicked is not updated.
Rather than using "window.ajaxRequest(url, data)", i've also tried (with the same result):
$.ajax({
type: "GET",
cache: false,
url: url,
data: $("#indexForm").serialize(),
success: function (data) {
var window = $("#Window").data("tWindow");
window.content(data);
window.center().open();
$("#progress").html('')
},
error: function (e) {
alert(e.Message);
}
});
Is it all possible to determine what I am doing wrong? Is it the ajax request? Only assuming that because removing it fixes the issue, but there might be more to it than that.
Thanks and of course if you need more info, ask :)
Thanks
EDIT
After suggestions from 3nigma, this is what I've updated to (still no luck)...
Telerik window definition:
#{Html.Telerik().Window()
.Name("Window")
.Title("Add Part")
.Draggable(true)
.Modal(true)
.Width(400)
.Visible(false)
.Height(270)
.ClientEvents(e => e.OnOpen("onWindowOpen"))
.Render();
}
jquery function which is an OnClick event for a button:
function AddBtnClicked() {
$("#Window").data('tWindow').center().open();
}
the onWindowOpen event:
function onWindowOpen(e) {
//e.preventDefault();
var data = #Html.Raw(Json.Encode(Model));
var d2 = $.toJSON(data);
$.ajax({
type: 'GET',
url: '#Url.Action("GetAddPart", "Jobs")',
data: d2,
contentType: 'application/json',
success: function (data) {
var window = $("#Window").data("tWindow");
window.content(data);
$("#progress").html('');
},
error: function (xhtr, e, e2) {
alert(e +'\n' + xhtr.responseText);
}
});
};
OK.
Issue was related to this line in the Partial View:
<script src="#Url.Content("~/Scripts/ValidationJScript.js")" type="text/javascript"></script>
As soon as I took that out, it all works. Not sure why that was causing the issue - I don't think it had been previously been loaded but maybe it had which was causing the problem.
Thanks to 3nigma for your thoughts, nonetheless!
At work I have been tasked with adding additional functionality to an existing MVC 3/Razor project. I haven't used MVC before, but am quite versed with Web Forms.
However, I am not quite sure where to place everything I need.
When the app is first loaded, a login page appears. When the user logs in successfully, the user sees a dashboard type page.
The new functionality is to detect whether the user has FollowUpItems with a Due Date < Now. If Count > 0 then display a Modal popup with some text and a link to 'View Followup Items'.
There is already a controller and action made for viewing Followup items. I need to display the modal, and I would like to make the modal a reuseable type of object - I am assuming/thinking a PartialView where I can pass in the name of the Controller, Action, Params for a possible ActionLink that I would display in the modal popup, and the message text, etc.
I need a little guidance on how to open the modal since it isn't attached to a click, but rather to whether an expression evaluates true or false, and where the best place for the pieces are.
Thanks in advance for the guidance
I would detect if the user has FollowUpItems in the Action that loads the dashboard page, and store that information in the ViewBag. For example,
public ActionResult Dashboard()
{
ViewBag.HasFollowupItems = UserHasFollowupItems();
return View();
}
In this example, UserHasFollowupItems() returns a string, something like 'true' or false'.
In the dashboard view, add an empty div into which the modal data will be loaded
<div id="followup_items"></div>
then add a document.ready() in the same view which defines the modal and determines if the modal should be loaded:
$(document).ready(function ()
{
// define modal
$("#followup_items").dialog({
autoOpen: false,
height: 'auto',
width: 825,
title: 'Followup Items',
position: [75, 75],
modal: true,
draggable: true,
closeOnEscape: true,
buttons: {
'Close': function ()
{
$(this).dialog('close');
}
},
close: function ()
{
$('.ui-widget-content').removeClass('ui-state-error');
},
});
if(#ViewBag.HasFollowupItems == 'true')
{
$('#followup_items').load("/FollowupItems/Load", function (data, txtStatus, XMLHttpRequest)
{
$('#followup_items').dialog('open');
}
});
});
In this example /FollowupItems/Load is the URL to the proper controller/action that generates the data for the view. You are correct, the view for this would be a partial view, loaded into the empty followup_items div on the page.
So you can use the #ViewBag object anywhere in the view, in this case passing in your boolean indicating if the modal should be loaded/opened. I have not found a way to use ViewBag in an external javascript file, so I typically use embedded script tags in my views so I can use the ViewBag.
You could also add in the user id in the same way (/FollowupItems/Load/#ViewBag.Userid), or any other data the followup action needs.
So I have a view that allows users to Approve or Reject items listed on the page. When approved, I simply use the #Ajax.ActionLink to post to the appropriate controller action. When the user Rejects an item, the user is required to enter a reason for the rejection. I'm found code on the internet that gave me a popup dialog and added a textbox and OK/Cancel buttons. I can capture the input from the user and show it in an alert, but now I need to complete it and I'm not sure how.
1st - I need add functionality to pass to my jquery link handler, the ID associated with the Item being rejected.
2nd - I need a way to call my Controller Action from the jquery.
Here is the code I have up to this point.
My link is simply an 'a' tag. I can't see to post the code for this without removing the <>
a href="#dialog" name="modal" Reject a
My script handles this here
$(document).ready(function () {
//select all the a tag with name equal to modal
$('a[name=modal]').click(function (e) {
//Cancel the link behavior
e.preventDefault();
//Get the A tag
var id = $(this).attr('href');
//Get the screen height and width
var maskHeight = $(document).height();
var maskWidth = $(window).width();
//Set heigth and width to mask to fill up the whole screen
$('#mask').css({ 'width': maskWidth, 'height': maskHeight });
//transition effect
$('#mask').fadeIn(1000);
$('#mask').fadeTo("slow", 0.8);
//Get the window height and width
var winH = $(window).height();
var winW = $(window).width();
//Set the popup window to center
$(id).css('top', winH / 2 - $(id).height() / 2);
$(id).css('left', winW / 2 - $(id).width() / 2);
//transition effect
$(id).val('');
$(id).fadeIn(2000);
});
Here is my pop up dialog and the mask that grays out the screen when the dialog is opened.
<div id="boxes">
<div id="dialog" class="window">
Enter the reason for rejection:</br>
<textarea class="multiline" id="rejectreason" rows="10" cols="20"></textarea><br/>
<div style="margin-left: 120px"><input type="button" value="OK" class="ok" style="width:70px"/> <input type="button" value="Cancel" style="width:70px" class="close"/>
</div>
</div>
<!-- Mask to cover the whole screen -->
<div id="mask"></div>
</div>
It could be that I'm going about this completely wrong, but it's all I could find on line and pieced it all together from there. As this is my first experience with jquery and MVC, I'm struggling a bit here. Any help would be greatly appreciated.
Thanks
UPDATE
OK, so I added a data-id attribute to my link that allows me to get the ID of the link clicked. I tested it using this code and it works.
var iD = $(this).attr('data-id');
I now need to pass this value to my dialog so I can then retrieve it again when the OK button on the dialog is clicked. I can set a hidden field on the page if necessary and retrieve it from there.
Here is some code to get you on the right path...
jQuery Ajax:
$(document).ready(function () {
$("#InputButtonId").click(function () {
$.ajax({
url: '#Url.Action("SomeAction", "Controller")',
type: 'POST',
data: { id: $("#hidden").val(), reason: $("#rejectreason").html },
dataType: "json",
beforeSend: function () {
},
success: function (result) {
// Do action if success
},
error: function (result) {
// Do action if error
}
});
return false;
});
});
And the controller action:
[HttpPost]
public JsonResult SomeAction(string id, string reason)
{
//Perform Actions
return Json(new
{
value1 = value1,
value2 = value2
}, JsonRequestBehavior.AllowGet);
}
Hope this helps.