2

I have a table:

<table id="Equipment-Table" class="table table-bordered table-hover">
    <thead>
        <tr>
            <th class="text-center">
                @Html.DisplayNameFor(model => model.TypeOfEquipment)
            </th>
            <th class="text-center">
                @Html.DisplayNameFor(model => model.Deleted)
            </th>
            <th></th>
        </tr>
    </thead>

    <tbody>
        @foreach (var item in Model)
        {
            <tr class="text-center">
                <td>
                    @Html.DisplayFor(modelItem => item.TypeOfEquipment)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Deleted)
                </td>
                <td>
                    @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
                    @Html.ActionLink("Details", "Details", new { id = item.Id }) |
                    @Html.ActionLink("Delete", "Delete", new { id = item.Id })
                </td>
            </tr>
        }
    </tbody>
</table>

I am using jQuery DataTables to style it and give it functionality.

This produces this:

enter image description here

My goal:

Order by the Deleted column. I want deleted items to be at the bottom of the list.

Here is what I have so far:

$(document).ready(function() {
    var equipmentTable = $("#Equipment-Table").DataTable({
        "order": [1, "asc"],
        "aoColumnDefs": [
            { "bSortable": false, "aTargets": [1, 2] },
            { "bSearchable": false, "aTargets": [1, 2] }
        ]
    });
});

How can I make this happen?

Update

<tr class="text-center">
    <td>
        @Html.DisplayFor(modelItem => item.TypeOfEquipment)
    </td>
    @if (item.Deleted)
    {
        <td data-order="1">
            @Html.DisplayFor(modelItem => item.Deleted)
        </td>
    }
    else
    {
        <td data-order="0">
            @Html.DisplayFor(modelItem => item.Deleted)
        </td>
    }

    <td>
        @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
        @Html.ActionLink("Details", "Details", new { id = item.Id }) |
        @Html.ActionLink("Delete", "Delete", new { id = item.Id })
    </td>
</tr>


$(document).ready(function() {
    var equipmentTable = $("#Equipment-Table").DataTable({
        "aoColumnDefs": [
            { "bSortable": false, "aTargets": [1, 2] },
            { "bSearchable": false, "aTargets": [1, 2] }
        ]
    });

    $('#Equipment-Table input[type="checkbox"]').on('change', function () {
        // Update data-sort on closest <td>
        $(this).closest('td').attr('data-order', this.checked ? 1 : 0);

        // Store row reference so we can reset its data
        var $tr = $(this).closest('tr');

        // Force resorting
        equipmentTable
          .row($tr)
          .invalidate()
          .order([1, 'asc'])
          .draw();
    });
});

1 Answer 1

3

You are using the legacy DataTables API: you should avoid using that, because it is being replaced by a more verbose and readable one.

You can sort your checkbox column programatically by using a combination of the following strategy:

  • When the page is first rendered, set the data-sort / data-order attribute to reflect the (un)checked status. In the example below, I settled for 0 for unchecked and 1 for checked. This should be handled by your templating/layout logic.

    <!-- Rendered markup for UNCHECKED -->
    <td data-order="0"><input type="checkbox" /></td>
    
    <!-- Rendered markup for CHECKED -->
    <td data-order="1"><input type="checkbox" checked /></td>
    
  • We bind a click event handler to the checkbox input. When the onChange event is fired, we simply:

    1. Dynamically update the data-sort/data-order attribute based on the checked status of the checkbox
    2. Invalidate the cached data stored for the row (so DataTables will have to reindex the data-sort/data-order attribute), using .row().invalidate()
    3. Resort the table using .sort()
    4. Trigger redrawing using .draw(), as the step above does not reflow/redraw the table

Here is a proof-of-concept example:

$(document).ready(function() {
  var equipmentTable = $("#Equipment-Table").DataTable({
    "order": [1, "asc"]
  });

  // Listen to change event from checkbox to trigger re-sorting
  $('#Equipment-Table input[type="checkbox"]').on('change', function() {
    // Update data-sort on closest <td>
    $(this).closest('td').attr('data-order', this.checked ? 1 : 0);
    
    // Store row reference so we can reset its data
    var $tr = $(this).closest('tr');
    
    // Force resorting
    equipmentTable
      .row($tr)
      .invalidate()
      .order([ 1, 'asc' ])
      .draw();
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.16/js/jquery.dataTables.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet" />

<table id="Equipment-Table" class="table table-bordered table-hover">
  <thead>
    <tr>
      <th class="text-center">
        Type of Eqiupment
      </th>
      <th class="text-center">
        Deleted
      </th>
      <th></th>
    </tr>
  </thead>

  <tbody>
    <tr class="text-center">
      <td>Lorem</td>
      <td data-order="0"><input type="checkbox" /></td>
      <td>...</td>
    </tr>
    <tr class="text-center">
      <td>Ipsum</td>
      <td data-order="0"><input type="checkbox" /></td>
      <td>...</td>
    </tr>
    <tr class="text-center">
      <td>Dolor</td>
      <td data-order="1"><input type="checkbox" checked /></td>
      <td>...</td>
    </tr>
    <tr class="text-center">
      <td>Sit</td>
      <td data-order="1"><input type="checkbox" checked /></td>
      <td>...</td>
    </tr>
    <tr class="text-center">
      <td>Amet</td>
      <td data-order="0"><input type="checkbox" /></td>
      <td>...</td>
    </tr>
  </tbody>
</table>

Update

It seems like OP is only interested in enforcing initial sorting of the table, while disabling user-initiated sorting and search. The checkboxes are also disabled by default, which means we do not need to bind event listeners to them since we do not expect the user to toggle this option. This can be done with the following config:

{
  "order": [1, "asc"],
  "columnDefs": [
    { "orderable": false, "targets": [0,1,2] },
  ],
  "searching": false
}

Proof-of-concept:

$(document).ready(function() {
  var equipmentTable = $("#Equipment-Table").DataTable({
    "order": [1, "asc"],
    "columnDefs": [{
      "orderable": false,
      "targets": [0, 1, 2]
    }],
    "searching": false
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.16/js/jquery.dataTables.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet" />

<table id="Equipment-Table" class="table table-bordered table-hover">
  <thead>
    <tr>
      <th class="text-center">
        Type of Eqiupment
      </th>
      <th class="text-center">
        Deleted
      </th>
      <th></th>
    </tr>
  </thead>

  <tbody>
    <tr class="text-center">
      <td>Lorem</td>
      <td data-order="0"><input type="checkbox" disabled /></td>
      <td>...</td>
    </tr>
    <tr class="text-center">
      <td>Ipsum</td>
      <td data-order="0"><input type="checkbox" disabled /></td>
      <td>...</td>
    </tr>
    <tr class="text-center">
      <td>Dolor</td>
      <td data-order="1"><input type="checkbox" checked disabled /></td>
      <td>...</td>
    </tr>
    <tr class="text-center">
      <td>Sit</td>
      <td data-order="1"><input type="checkbox" checked disabled /></td>
      <td>...</td>
    </tr>
    <tr class="text-center">
      <td>Amet</td>
      <td data-order="0"><input type="checkbox" disabled /></td>
      <td>...</td>
    </tr>
  </tbody>
</table>

Sign up to request clarification or add additional context in comments.

5 Comments

I am trying this, but it is not working for me. See my update
@GTown-Coder I can't troubleshoot for you until you post an MCVE: there is no way I can render the HTML for you. Can you update your question so that you post a working example, where you have the rendered markup + loaded the appropriate plugins? Just like the code snippet in my answer.
@GTown-Coder If you read my answer carefully, I mentioned about using the modern API for DataTables. Replacing your settings and using "order": [1, "asc"] fixed the issue for me. Since you have disabled the checkboxes, I suppose you don't intend for the user to change them. In that case we do not need to attach event handlers to them: jsfiddle.net/teddyrised/ezsx4d5j/1
Okay, but I don't want columns 1 and 2 to be able to be searched or sorted.. I just want column 1 ordered on page load.
@GTown-Coder Then use columnDefs to turn off ordering for users: jsfiddle.net/teddyrised/ezsx4d5j/2. If you do not want columns 1 and 2 to be searchable, you are better off turning off the search function using "searching": false in the config: jsfiddle.net/teddyrised/ezsx4d5j/3 since the 3rd column has nothing to search for anyway. See updated answer.

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.