5

So I wanted to create a toggle-button for a table, where I can make an async call to update a database record (enable/disable).

img

After some trial and error, I have managed to get it working - but it feels like there must be a more elegant way.

  • I don't like repeating my image-tag in my controller, obviously... How can I avoid that in an elegant way?
  • Is there an overall better way to approach this that what I have done?

Here is my code in the controller:

public ActionResult ToggleEnabled(int id)
    {
        if (Request.IsAjaxRequest())
        {
            var p = this.PageRepository.GetPage(id);
            p.Enabled = p.Enabled != true;
            this.PageRepository.Edit(p);
            return p.Enabled ? Content("<img src='/Content/icons/tick.png' border=0  />") : Content("<img src='/Content/icons/tick_grey.png' border=0  />");
        }
        return Content("Error");
    }

And the view...:

<% var img = Model.Enabled ? "tick.png" : "tick_grey.png"; %>
<% foreach (var item in Model)
       { %>
...
<td align="center">
    <%=Ajax.ActionLink("[replacethis]", 
        "ToggleEnabled", 
                new { id = Model.ID }, 
                new AjaxOptions { UpdateTargetId = "toggleimage" + Model.ID }).Replace("[replacethis]",
                string.Format("<div id='toggleimage{0}'><img src='/Content/icons/{1}' border='0' alt='toggle'/></div>", 
                Model.ID, Model.Enabled ? "tick.png" : "tick_grey.png"))%>
</td>
...
<% } %>

The trick/hack with the Ajax.Actionlink using an image was found here.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Kjensen
  • 12,447
  • 36
  • 109
  • 171
  • I actually like the way you did it. I don't see any obvious way to make it simpler. As you pointed out, your image logic is duplicated in the controller and the view, but you need the logic in the view for the page load, and you need the logic in the controller for the Ajax call. – Robert Harvey Jul 04 '09 at 01:02
  • Trying to rewrite this in razor Mvc 3, I get an error with "replace". It says System.Web.MVC.MVChtmlString does not contain a defintion... – Chaka Dec 23 '12 at 15:30
  • Any help on how to rewrite in razor? – Chaka Dec 23 '12 at 15:31

2 Answers2

3

How about rendering checkbox based on whether the model is enabled or not.

In jQuery, you can replace those checkboxes with your images. Something like

Your document.ready code may look like,

$(document).ready(
function()
{
    $('.enabledCheckbox').each(
        function()
        {
            var image = $(this).checked ? 'tick.png' ? 'tick_grey.png';
            $(this).parent.click(
                function()
                {
                    if($(this).is('image'))
                        toggleEnabledStatus(); //write code in toggleEnabledStatus to toggle the state of the model on server side.
                }     
                );
            $(this).parent.html('<img src=' + image + '/>');
        }
    );
}
);

Alternatively, you can use plugin like jquery-checkbox to give them any fancy styling you may think of.

SolutionYogi
  • 31,807
  • 12
  • 70
  • 78
  • I would say this is the best way to do it - that way you leave the html page only with html and don't clutter it with all that extra code – sirrocco Jul 04 '09 at 08:55
0

If elegance is what you want, I would use a jQuery web service request to make a AJAX request to the underlying ASPX page instead. It's pretty darned elegant, because all you need on your ASPX page is a static [WebMethod] to perform the actual action, and a $.ajax() call from jQuery.

Dave Markle
  • 95,573
  • 20
  • 147
  • 170