EthicsComputerCourses
Join training +91 90532 10052

jQuery UI & DataTables-Style Widgets

jQuery · Lesson 25 of 36 Advanced 7 min read Updated

A widget is a ready-made interface component: a date picker, a dialog box, an autocomplete box, a sortable list, a data grid with search and paging. Admin panels, ERP screens and school management systems built in the jQuery years are full of them, usually from jQuery UI (the official widget collection) and DataTables (the most common table plugin). As a maintainer you rarely write a widget, but you constantly configure, update and debug them.

This lesson is a practical overview: what these libraries are, where they stand in 2026, the life cycle every widget follows, and which native HTML features can replace them in new code. The examples are our own; the official documentation (api.jqueryui.com and datatables.net) lists every option.

Where the main libraries stand

LibraryLatest version (checked November 2026)Status
jQuery UI1.14.2 (January 2026)Maintenance only: kept compatible with new jQuery releases and patched for security, no new features. Tested by its team with jQuery 1.12.4 up to 4.0.0.
DataTables3.1.5Since version 3 (2026) it no longer needs jQuery, but it still registers itself as a jQuery plugin when jQuery is on the page.
Select2, Slick, Chosen and similarvariesThird-party plugins with their own release cycles. Check each one's repository before upgrading jQuery.

Two practical lessons from this table. First, old widget versions are a security issue: jQuery UI versions before 1.13.0 have known cross-site scripting (XSS) bugs in options such as the datepicker's text options, and 1.13.2 fixed another, so security scanners flag them. Second, a widget can block your jQuery upgrade: if a plugin calls an API that jQuery 4 removed, the whole page waits for it (see jQuery 3 to 4: What Changed).

The widget life cycle

Every widget, from any library, goes through the same five stages. Most widget bugs come from getting one of them wrong.

  1. Load the CSS, then jQuery, then the widget's JavaScript. A widget file loaded before jQuery, or a second copy of jQuery loaded after it, gives "is not a function" errors.
  2. Initialise once on elements that exist: $("#city").autocomplete({...}). Initialising the same element twice gives duplicate handlers or a warning.
  3. Talk to it through its methods, not by changing its internal HTML: $("#dlg").dialog("open"), $("#city").autocomplete("option", "minLength", 2).
  4. Listen to its events to react to the user: select for autocomplete, close for dialogs, draw for DataTables.
  5. Destroy it before removing or re-rendering its element: $("#dlg").dialog("destroy"). Removing elements with jQuery's .remove() also destroys jQuery UI widgets automatically.

Here are two jQuery UI widgets going through that life cycle. Type "Pu" into the city box, pick a city, and confirm in the dialog:

HTMLTry it yourself
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>jQuery UI widgets</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-ui@1.14.2/dist/themes/base/jquery-ui.min.css">
  <style>body { font-family: system-ui, sans-serif; }</style>
</head>
<body>
  <label for="city">Exam centre city</label>
  <input id="city" placeholder="Type Pu or Ja">
  <p id="chosen">No centre chosen yet.</p>

  <div id="confirm" title="Confirm exam centre">
    <p>Book a seat at the <strong id="confirm-city"></strong> centre?</p>
  </div>

  <!-- Step 1: CSS above, then jQuery, then jQuery UI -->
  <script src="https://cdn.jsdelivr.net/npm/jquery@4.0.0/dist/jquery.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/jquery-ui@1.14.2/dist/jquery-ui.min.js"></script>
  <script>
    const centres = ["Pune", "Puducherry", "Purnia", "Jaipur", "Jamshedpur", "Kochi", "Lucknow"];

    // Step 2: initialise once
    $("#confirm").dialog({
      autoOpen: false,
      modal: true,
      buttons: {
        Book: function () {
          $("#chosen").text("Seat booked at " + $("#confirm-city").text() + ".");
          $(this).dialog("close");                       // step 3: call a method
        },
        Cancel: function () { $(this).dialog("close"); },
      },
    });

    $("#city").autocomplete({
      source: centres,
      minLength: 2,
      select: function (event, ui) {                     // step 4: react to an event
        $("#confirm-city").text(ui.item.value);          // .text(), never .html()
        $("#confirm").dialog("open");
      },
    });
  </script>
</body>
</html>

Notice that the code never touches the HTML that jQuery UI generates (the suggestion list, the dialog's title bar and buttons). That HTML can change between versions; the methods, options and events are the stable, documented interface.

DataTables: search, sort and paging for tables

DataTables turns a plain <table> into a grid with search, sorting and paging. On a jQuery page it is usually started with $("#table").DataTable({...}), which returns an API object for later calls:

HTMLTry it yourself
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>DataTables grid</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/datatables.net-dt@3.1.5/css/dataTables.dataTables.min.css">
  <style>body { font-family: system-ui, sans-serif; max-inline-size: 40rem; }</style>
</head>
<body>
  <table id="students">
    <thead><tr><th>Name</th><th>City</th><th>Marks</th></tr></thead>
    <tbody>
      <tr><td>Aarav</td><td>Pune</td><td>88</td></tr>
      <tr><td>Priya</td><td>Jaipur</td><td>92</td></tr>
      <tr><td>Kabir</td><td>Rohtak</td><td>75</td></tr>
      <tr><td>Meera</td><td>Kochi</td><td>81</td></tr>
      <tr><td>Rohan</td><td>Pune</td><td>67</td></tr>
      <tr><td>Ananya</td><td>Lucknow</td><td>95</td></tr>
      <tr><td>Farhan</td><td>Jaipur</td><td>79</td></tr>
    </tbody>
  </table>
  <p><button id="add">Add Isha (Kochi, 90)</button> <button id="pune">Show only Pune</button></p>
  <p id="info"></p>

  <script src="https://cdn.jsdelivr.net/npm/jquery@4.0.0/dist/jquery.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/datatables.net@3.1.5/js/dataTables.min.js"></script>
  <script>
    const table = $("#students").DataTable({
      pageLength: 5,
      order: [[2, "desc"]],                 // sort by Marks, highest first
    });

    // Use the API, not direct DOM edits, so DataTables knows about the change
    $("#add").on("click", function () {
      table.row.add(["Isha", "Kochi", 90]).draw();
      $(this).prop("disabled", true);
    });
    $("#pune").on("click", function () {
      table.search("Pune").draw();
    });

    table.on("draw", function () {
      $("#info").text("Rows matching the search: " + table.rows({ search: "applied" }).count());
    });
  </script>
</body>
</html>

Three facts help when you maintain DataTables code:

  • Change data through the API (row.add(), row().remove(), clear(), then draw()). If you append a <tr> with jQuery, DataTables does not know it exists and the next sort or search hides it.
  • Big tables need server-side processing. With options such as serverSide: true and an ajax URL, the server does the searching, sorting and paging, and sends one page at a time. Loading 50,000 rows into the browser makes the page freeze.
  • Version 3 changed callback context. In callbacks such as rowCallback, this is no longer a jQuery object but DataTables' own DOM helper. Old code that calls jQuery methods on this must wrap it with $(this) or use the DataTables API. Without jQuery, the same table is created with new DataTable("#students", {...}).

Native replacements for new code

Many jQuery UI widgets now have a built-in HTML equivalent. Native elements need no library, work with the phone's own keyboard and pickers, and get accessibility features from the browser:

jQuery UI widgetNative HTMLNotes
Datepicker<input type="date">The browser's picker; the value is always YYYY-MM-DD
Dialog<dialog> with showModal()Focus handling and Escape key built in
Autocomplete (fixed list)<input list="..."> with <datalist>For server suggestions, combine with a debounced fetch()
Tabs, Accordion<details> (with name for one-open-at-a-time)Real tabs still need a small script with ARIA roles
Tooltipthe popover attributeKeep important help visible as normal text instead
Sortable, Draggableno direct equivalentThe HTML drag and drop API or a small library
DataTables gridno direct equivalentSmall tables: a short sort/filter script; large ones: server-side paging
HTML
<!-- The same exam-centre form with no library at all -->
<label for="city">Exam centre city</label>
<input id="city" list="centres">
<datalist id="centres">
  <option value="Pune"></option><option value="Jaipur"></option><option value="Kochi"></option>
</datalist>

<dialog id="confirm">
  <p>Book a seat at the <strong id="confirm-city"></strong> centre?</p>
  <form method="dialog"><button value="book">Book</button> <button value="cancel">Cancel</button></form>
</dialog>

Common mistakes

  • Editing the widget's generated HTML instead of using its options and methods. Your change breaks on the next upgrade.
  • Initialising again after every AJAX load without destroying first. Destroy, then re-create, or initialise only the new elements.
  • Adding table rows with jQuery on a DataTables table. Use row.add() and draw().
  • Loading the full jQuery UI bundle for one widget. Custom builds or the native element are much lighter.
  • Leaving jQuery UI below 1.13.2 because "it works". Old versions have published XSS vulnerabilities.

Key points

  • jQuery UI 1.14.2 is maintenance-only but supports jQuery 4; DataTables 3 no longer needs jQuery but still works as a jQuery plugin.
  • Every widget follows the same life cycle: load in order, initialise once, use methods, listen to events, destroy.
  • Talk to widgets through their documented options, methods and events, never their internal HTML.
  • Change DataTables data through its API, and use server-side processing for large tables.
  • For new code, prefer <input type="date">, <dialog>, <datalist>, <details> and popover.

Exercise

Using the DataTables example, add a "Remove lowest" button that deletes the student with the lowest marks through the API, and a "Clear search" button. Show the number of rows left in the #info paragraph after every change. Hint: table.rows().data() returns the row data, and table.row(index).remove().draw() removes a row.

Show solution
JavaScript
$("<button>", { text: "Remove lowest" }).appendTo("p:has(#add)").on("click", function () {
  let lowestIndex = null;
  let lowestMarks = Infinity;
  table.rows().every(function (rowIdx) {
    const marks = Number(this.data()[2]);
    if (marks < lowestMarks) { lowestMarks = marks; lowestIndex = rowIdx; }
  });
  if (lowestIndex !== null) table.row(lowestIndex).remove().draw();
});

$("<button>", { text: "Clear search" }).appendTo("p:has(#add)").on("click", function () {
  table.search("").draw();
});

table.on("draw", function () {
  $("#info").text("Rows left: " + table.rows().count()
    + ", matching the search: " + table.rows({ search: "applied" }).count());
});

rows().every() visits each row with its index, so the lowest mark can be found from the data, and row(index).remove().draw() removes it through the API. The draw event fires after every change, so the counter stays correct.

Quick Quiz

1. What is the status of jQuery UI in 2026?

2. You add a <tr> to a DataTables table with $("tbody").append(...). After sorting, the row disappears. Why?

3. Which native element replaces the jQuery UI Dialog in new code?

4. What should you do before re-rendering HTML that contains an initialised widget with plain DOM code?

Learn jQuery with a mentor

Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call