7

I would like to update the database when someone checked a box that represents a bit field on the row. I have been going off of this question: Ajax.ActionLink(...) with checkbox Here is my code in the cshtml file:

@foreach (var item in Model) {
<tr>
    <td>
        @Html.DisplayFor(modelItem => item.Macro_Name)
    </td>
    <td>
        @Html.CheckBoxFor(modelItem => item.Claimed, new { id = item.Macro_Name, data_url = Url.Action("ToggleClaim", "MacroStatus")})
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Date_Claimed)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Username)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Finished)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Date_Completed)
    </td>
    <td>
        @Html.ActionLink("Edit", "Edit", new { id=item.Macro_Name }) |
        @Html.ActionLink("Details", "Details", new { id = item.Macro_Name }) |
        @Html.ActionLink("Delete", "Delete", new { id = item.Macro_Name })
    </td>
</tr>
}

In the MacroStatusController class I have the following action:

    public ActionResult ToggleClaim(string id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        MacroStatus macroStatus = db.MacroStatus1.Find(id);
        if (macroStatus == null)
        {
            return HttpNotFound();
        }

        if (ModelState.IsValid)
        {
            macroStatus.Date_Claimed = DateTime.Now;
            db.Entry(macroStatus).State = EntityState.Modified;
            db.SaveChanges();
        }

        return new HttpStatusCodeResult(HttpStatusCode.OK);
    }

However, ToggleClaim isn't running when I check or uncheck the box. There are no compile errors. This is my first try with asp.net mvc, what am I doing wrong?

6
  • The data-url attribute only contains some url now. There needs to be some piece of Javascript that uses it. Commented Oct 14, 2015 at 18:59
  • 1
    There are a ton of ways to approach this, but you need something to do an AJAX call to a server endpoint (probably a Web API method, since you're using ASP.net MVC) when you check that box. The "quick and dirty" answer is to use a jQuery selector for you checkbox and register a function using $([selector]).change(function(){}); You could also bind the checkbox to a kendo viewmodel function, or any number of other approaches. Commented Oct 14, 2015 at 19:07
  • You could look here, too: stackoverflow.com/questions/1784412/… Commented Oct 14, 2015 at 19:09
  • @EricBurcham The key point is sending an ajax request when checkbox changed. Commented Oct 14, 2015 at 19:22
  • @RezaAghaei - I thought that was clear in my comment, but you are absolutely correct. Commented Oct 14, 2015 at 19:26

4 Answers 4

7

You will need ajax for this. First, add a class to the checkboxes so you will have a hook to attach your click event.

@Html.CheckBoxFor(modelItem => item.Claimed, new { id = item.Macro_Name, @class = "toggle" data_url = Url.Action("ToggleClaim", "MacroStatus")})

Now add your javascript.

@section scripts {
    <script>
        $(function() {
            $('.toggle').change(function() {
                var self = $(this);
                var url = self.data('url');
                var id = self.attr('id');
                var value = self.prop('checked');

                $.ajax({
                    url: url,
                    data: { id: id },
                    type: 'POST',
                    success: function(response) {
                        alert(response);
                    }
                });
            });
        });
    </script>
}
Sign up to request clarification or add additional context in comments.

3 Comments

, class = "toggle" is giving me a syntax error here. Is that a valid keyword here?
Sorry, class is a reserved word, escape it with @ - @class = "toggle"
hi how to update the row upon Ajax success/fail. For e.g. if Status was a col in the row. And if Approved/Rejected was a radio button with some notes, so if I want to -- toggle the color of the row, and update the value of status in the row.
3

The key point is sending an ajax request when checkbox changed.

As mentioned in comments by Eric, You can trigger that action using many different ways. for example, put this script in your codes:

<script>
    $(function () {
        $('#Claimed').change(function () {
            $.ajax({
                url: '/ToggleClaim/MacroStatus/@item.Macro_Name',
                cache: false,
                method: 'GET',
                success: function (data) { alert('success'); },
                error: function () { alert('error'); }
            });
        });
    });
</script> 

And correct checkbox code this way:

<td>
    @Html.CheckBoxFor(modelItem => item.Claimed)
</td>

The above code, triggers the action each time you check or uncheck the checkbox, you can simply check if the checkbox is checked and then send ajax request.

5 Comments

@EricBurcham Thank you:)
To pass the correct macro name like you are trying to do, you would have to put this inside the foreach loop. You shouldn't do that.
@JB06 Which macro name? Which loop? Do what? ;)
Your url string won't work unless you put this inside the foreach, how else would you use @item?
Very good point! I have never seen that loop yet;) And this way I should not use Id too!
0

The reason is that when checkbox is unchecked & form is submitted; no form field related to checkbox is submitted. You either have to use JavaScript to add hidden variable as described in Post the checkboxes that are unchecked, or make a Ajax hit when checkbox is checked. jQuery Ajax checkbox state

Comments

0

This can be done without script using fontawesome and a anchor with a standard controller.

Add a link to the css file in your layout page.

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css"           
integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" 
crossorigin="anonymous">

In your view or display template add an anchor

<a asp-controller="MacroStatus" asp-action="ToggleClaim" asp-route- 
id="item.Macro_Name">
@if (item.Claimed)
{
    <span class="fas fa-toggle-on fa-2x"></span>
}
else
{
    <span class="fas fa-toggle-off fa-2x"></span>
}
</a>

It looks like a checkbox and is clickable and is also great if you have multiple instances in one view, for example if you are using a display template for an array of objects.

The above can be made very clean and re-usable by using a component for the toggle on/off part.

<vc:toggle-on-off toggle="@item.Claimed"></vc:toggle-on-off>

Then it would look something like:

<a asp-controller="MacroStatus" asp-action="ToggleClaim" asp-route- 
id="item.Macro_Name">
    <vc:toggle-on-off toggle="@item.Claimed"></vc:toggle-on-off>
</a>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.