Replacing OuterHTML with AJAXHelper.ActionLink


There are various wayswhich provides unobtrusive way of updating UI with response from server via AJAX. One such option provided by MVC framework is Ajax.ActionLink. For example,
@Ajax.ActionLink
(
"TextOfLink",
"ActionName",
"ControllerName",
new AjaxOptions() { UpdateTargetId = "DivToBeReplaced"}
)
Above code generates a link which when clicked, calls an action called “ActionName” of the controller “ControllerName” and what ever is returned from this action, is displayed in a div with id “DivToBeReplaced”. That’s so easy!But there is a minor caveat in using UpdateTargetID. By default, it replaces the contents of div and not the div itself. Which means in following Razor code,

<div id="mydiv">
Some Text
@Ajax.ActionLink(
"Refresh",
"Index",
new AjaxOptions(){UpdateTargetId = "myDiv"}
<div>

Clicking on generated action link would result in following:
<div id="mydiv">
<div id="mydiv">
Some Text
@Ajax.ActionLink
(
"Refresh",
"Index",
new AjaxOptions(){UpdateTargetId "myDiv"}
)
</div>
</div>
This is so because action link will replace what ever comes from server with the content inside mydiv and not mydiv itself (in other words, it replaces innerHTML and not OuterHTML)

Fix: Instead of using UpdateTargetId, use OnComplete event handler which takes as input a JavaScript method name (automatically called when view response is received from server)

@Ajax.ActionLink("TextOfLink",
"ActionName",
"ControllerName",
new AjaxOptions() { OnComplete= "setMyDiv"})
and in script:

function setMyDiv(data)
{
$('#mydiv').replaceWith(data.responseText);
}
data is the object that contains response while responseText property returns response as a string. While divId is passed from view which needs to be replaced with response content. This gives a finer control over manipulating response and playing with DOM.

Q) What if div id is dynamically generated and hence not known in advance?
A) This is what I was stuck upon and found a cute hack. Internally, JQuery contains response in a variable called “xhr”. So, I was able to solve this problem as following:

@Ajax.ActionLink(
"TextOfLink",
"ActionName",
"ControllerName",
new AjaxOptions() { OnComplete= "setSomeDiv(xhr,'" + Model.UniqueID +"')" })

where Model.UniqeId is some property of model containing unique Id. And the script:

function setSomeDiv(data, divId)
{
$(document).find('#' + divId).replaceWith(data.responseText);
}

This works great!! Hope it helps someone!!

Do let me know if you've a better approach.

Comments

Popular posts from this blog

How to show only month and year fields in android Date-picker?

How to construct a B+ tree with example

Conflict Serializability in database