Reputation: 25513
I'm trying to figure out the best way to make an AJAX call to perform some action, and then do some jquery effect magic to make it look like something is happening.
This is the basic idea: I have a link that when the user clicks it I need to update my model to say that the user is interested in an item (on the server side). However, I would also like to fade out the link (it's a checkbox image I made), change classes around and then fade the link back in. Behavior is like this: when you're not interested in an item the link looks like an empty box, when you hover over it the check appears, when they click on it the link fades out and comes back with the check in the box, and now when they hover over it the check disappears (the behavior reverses).
My problem is the link doesn't seem to be able to keep track of where it is (whether its in a checked state or an unchecked state).
I've tried doing this multiple ways.
Example A:
<a href="#" onclick="oncheck(this,<%= item.ID %>)" class="notchecked"></a>
<script>
function oncheck(link, itemId)
{
//the UI effects are working correctly
if ($(link).hasClass("notchecked")
{
$(link).fadeOut();
$(link).removeClass("notchecked");
$(link).addClass("checked");
$(link).fadeIn("slow");
}
{
$(link).fadeOut();
$(link).removeClass("checked");
$(link).addClass("notchecked");
$(link).fadeIn("slow");
}
//do ajax request using jquery
//I don't really care about the results right now
//This doesn't work though, it never hits my controller action
$.get("Item/ChangeCheckedStatus", { itemId: itemId } );
}
</script>
I've also tried doing this with Microsoft Ajax libraries
Example B:
<%=Ajax.ActionLink(" ",
"Item",
"ChangeCheckedStatus",
new { itemId = item.ID },
new AjaxOptions { UpdateTargetId="bogusTarget", OnSuccess = "oncheck" },
new { @class="notchecked" });
<script>
function oncheck()
{
//the UI effects are not working correctly here
if ($(this).hasClass("notchecked")
{
$(this).fadeOut();
$(this).removeClass("notchecked");
$(this).addClass("checked");
$(this).fadeIn("slow");
}
{
$(this).fadeOut();
$(this).removeClass("checked");
$(this).addClass("notchecked");
$(this).fadeIn("slow");
}
}
</script>
With the MS AJAX libraries, I get to the controller action, and the item gets updated, but then the jquery effects don't work.
Is there an easier way to do what I'm trying to accomplish or am I just missing something obvious here??
UPDATE This is what the controller action looks like:
public string ChangeCheckedStatus(long itemId)
{
//do some stuff
return "What is going on???";
}
Note: other actions in the controller work fine, it's just this one (which is the only one used via AJAX btw).
Upvotes: 2
Views: 992
Reputation: 126547
When you call an action with AJAX, and determine that the action is never run (e.g., a breakpoint at the start of the action is never hit), then you should always look at the Net tab Firebug, or the response from the server in Fiddler. There are two things to examine, here:
Upvotes: 1
Reputation: 167
You should use the ajax method as suggested by daddywoodland. The success method will be called when the AJAX call is successful. However, the this reference will not refer to your link but the window instead. This is because by the time the success method is asynchronously called you're outside the scope of the original onclick handler and therefore the method is no longer owned by the link, hence this is no longer the link but reverts to the window. This was essentially the same problem as your Microsoft AJAX library example above.
The trick, then, is to declare the success method as a closure inside your onclick method and have that closure refer to the link. I've tested the code below and it works. I placed a breakpoint on the server side action and it was hit.
<script type="text/javascript" src="../../Scripts/jquery-1.2.6.js"></script>
<a href="#" onclick="onLinkClick(this, 44)" class="notchecked">Click here...</a>
<script type="text/javascript">
// Standard onclick handler.
function onLinkClick(link, itemId) {
// the function called asynchronously when the AJAX works
var onCheck = function() {
if ($(link).hasClass("notchecked")) {
$(link).fadeOut();
$(link).removeClass("notchecked");
$(link).addClass("checked");
$(link).fadeIn("slow");
}
else {
$(link).fadeOut();
$(link).removeClass("checked");
$(link).addClass("notchecked");
$(link).fadeIn("slow");
}
}
// do the AJAX
$.ajax({
type: 'GET',
url: 'Item/ChangeCheckedStatus',
dataType: 'html',
data: { itemId: itemId },
success: function(response) {
onCheck();
}
});
}
</script>
You should be able to copy and paste this. So let me know if it doesn't work.
Upvotes: 1
Reputation: 28703
Can you put a break point in the controller to make sure it's being called? Maybe a routing problem if not...
Upvotes: 0
Reputation: 1512
The jQuery $.ajax method allows you to react if the ajax call was successful. Run your animation once the call has succeeded.
$.ajax({
type: 'GET',
url: 'Item/ChangeCheckedStatus',
dataType: 'html',
data: { itemId: itemId },
success: function(response){
if(response == "success") {
onCheck();
}
}
});
function onCheck() {
if ($(this).hasClass("notchecked")
{
$(this).fadeOut();
$(this).removeClass("notchecked");
$(this).addClass("checked");
$(this).fadeIn("slow");
}
{
$(this).fadeOut();
$(this).removeClass("checked");
$(this).addClass("notchecked");
$(this).fadeIn("slow");
}
}
Upvotes: 0
Reputation: 855
Try something like this:
$.get('Item/ChangeCheckedStatus', { itemId: itemId } , 'html', function() {
if ($(this).hasClass("notchecked")
{
$(this).fadeOut();
$(this).removeClass("notchecked");
$(this).addClass("checked");
$(this).fadeIn("slow");
}
{
$(this).fadeOut();
$(this).removeClass("checked");
$(this).addClass("notchecked");
$(this).fadeIn("slow");
}
});
Upvotes: 0