Troubleshooting Bootstrap 4's Multiple Sort Functionality in Tables

The Bootstrap Tables "Multiple Sort" plugin ("Multiple Sort"), specifically the showMultiSort feature, is currently not functioning properly with Bootstrap 4. The demonstration available on the linked page shows visible issues.

While the button associated with the plugin is present in the Document Object Model (DOM), it does not display correctly to the end user.

$(function() {
  $('#table').bootstrapTable({
    data: getData(),
    search: true,
    showColumns: true,
    showMultiSort: true,
    sortPriority: getSortPriority()
  })
});

function getSortPriority() {
  return [{
    "sortName": "github.count.forks",
    "sortOrder": "desc"
  }, {
    "sortName": "github.count.stargazers",
    "sortOrder": "desc"
  }];
}

function getData() {
  return [{
    "github": {
      "name": "bootstrap-table",
      "count": {
        "stargazers": 768,
        "forks": 183
      },
      "description": "An extended Bootstrap table with radio, checkbox, sort, pagination, and other added features. (supports twitter bootstrap v2 and v3)"
    }
  }, {
    "github": {
      "name": "multiple-select",
      "count": {
        "stargazers": 365,
        "forks": 166
      },
      "description": "A jQuery plugin to select multiple elements with checkboxes :)"
    }
  }, {
    "github": {
      "name": "bootstrap-show-password",
      "count": {
        "stargazers": 37,
        "forks": 13
      },
      "description": "Show/hide password plugin for twitter bootstrap."
    }
  }]
}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="fb9994948f888f899a8bd68f9a99979ebbcad5cacfd5c9">[email protected]</a>/dist/bootstrap-table.min.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5a3835352e292e283b2a772e3b38363f1a6b746b6e7468">[email protected]</a>/dist/extensions/multiple-sort/bootstrap-table-multiple-sort.js"></script>

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link href="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="01636e6e7572757360712c7560636d6441302f30352f33">[email protected]</a>/dist/bootstrap-table.min.css" rel="stylesheet">


<table id="table">
  <thead>
    <tr>
      <th data-field="github.name" data-sortable="true">Name</th>
      <th data-field="github.count.stargazers" data-sortable="true">Stargazers</th>
      <th data-field="github.count.forks" data-sortable="true">Forks</th>
      <th data-field="github.description" data-sortable="true">Description</th>
    </tr>
  </thead>
</table>

Answer №1

To address the issue, I devised a jQuery plugin for resolving it.

(function($) {
  $.fixBootstrapMultisort = function() {
    let $button = $('.multi-sort'),
      $modal = $('div[id^="sortModal_"].modal'),
      $toolbar = $modal.find('.modal-dialog #toolbar');
    // Enclose the button within a button group element.
    $button.addClass('btn-secondary').wrap($('<div>').addClass('btn-group'));
    // Correct the alignment of the modal title.
    $modal.find('.modal-dialog .modal-content .modal-header .modal-title').css({ position: 'absolute', lineHeight: 1 });
    // Update the icons.
    $button.find('.fa.glyphicon-sort').removeClass('glyphicon-sort').addClass('fa-sort').css('width', '1em');
    $toolbar.find('i.glyphicon-plus').removeClass('glyphicon-plus').addClass('fa-plus');
    $toolbar.find('i.glyphicon-minus').removeClass('glyphicon-minus').addClass('fa-minus');
  };
})(jQuery);

Several adjustments were necessary to fix the problem:

  • The .multi-sort button was not enveloped in a div.btn-group element.
  • The icon used was .glyphicon-sort, instead of .fa-sort.
  • I specified the width of the button as 1em to resolve conflicts related to the default icon width.
  • The positioning of the modal window title required adjustment.

Functional demonstration

(function($) {
  $.fixBootstrapMultisort = function() {
    let $button = $('.multi-sort'),
      $modal = $('div[id^="sortModal_"].modal'),
      $toolbar = $modal.find('.modal-dialog #toolbar');
    // Enclose the button within a button group element.
    $button.addClass('btn-secondary').wrap($('<div>').addClass('btn-group'));
    // Correct the alignment of the modal title.
    $modal.find('.modal-dialog .modal-content .modal-header .modal-title').css({ position: 'absolute', lineHeight: 1 });
    // Update the icons.
    $button.find('.fa.glyphicon-sort').removeClass('glyphicon-sort').addClass('fa-sort').css('width', '1em');
    $toolbar.find('i.glyphicon-plus').removeClass('glyphicon-plus').addClass('fa-plus');
    $toolbar.find('i.glyphicon-minus').removeClass('glyphicon-minus').addClass('fa-minus');
  };
})(jQuery);

$(function() {
  $('#table').bootstrapTable({
    data: getData(),
    search: true,
    showColumns: true,
    showMultiSort: true,
    sortPriority: getSortPriority()
  });
  $.fixBootstrapMultisort();
});

function getSortPriority() {
  return [{
    "sortName": "github.count.forks",
    "sortOrder": "desc"
  }, {
    "sortName": "github.count.stargazers",
    "sortOrder": "desc"
  }];
}

function getData() {
  return [{
    "github": {
      "name": "bootstrap-table",
      "count": {
        "stargazers": 768,
        "forks": 183
      },
      "description": "An extended Bootstrap table with radio, checkbox, sort, pagination, and other added features. (supports twitter bootstrap v2 and v3)"
    }
  }, {
    "github": {
      "name": "multiple-select",
      "count": {
        "stargazers": 365,
        "forks": 166
      },
      "description": "A jQuery plugin to select multiple elements with checkboxes :)"
    }
  }, {
    "github": {
      "name": "bootstrap-show-password",
      "count": {
        "stargazers": 37,
        "forks": 13
      },
      "description": "Show/hide password plugin for twitter bootstrap."
    }
  }]
}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="72101d1d0601060013025f0613101e1732435c43465c40">[email protected]</a>/dist/bootstrap-table.min.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7d1f1212090e090f1c0d50091c1f11183d4c534c49534f">[email protected]</a>/dist/extensions/multiple-sort/bootstrap-table-multiple-sort.js"></script>

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link href="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="01636e6e7572757360712c7560636d6441302f30352f33">[email protected]</a>/dist/bootstrap-table.min.css" rel="stylesheet">


<table id="table">
  <thead>
    <tr>
      <th data-field="github.name" data-sortable="true">Name</th>
      <th data-field="github.count.stargazers" data-sortable="true">Stargazers</th>
      <th data-field="github.count.forks" data-sortable="true">Forks</th>
      <th data-field="github.description" data-sortable="true">Description</th>
    </tr>
  </thead>
</table>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Setting border radius for the first child of li dynamically using Javascript

I am currently working on creating a navigation bar that features rounded corners for the first and last children within an unordered list. My goal is to utilize the onclick javascript function to dynamically assign these rounded corners directly in JavaSc ...

Mastering the Art of Accelerating getJSON Array Data

Currently, I am facing a challenge with retrieving a large array (4MB) of data from the server side. I have been utilizing the jQuery getJSON method to obtain the array data and display it on the browser. However, this process has proven to be quite slow ...

Does v-if cause the jquery clock picker to malfunction?

Here is my unique div where the clockpicker library functions correctly. <div class="input-group clockpicker"> <input type="text" class="form-control" value="18:00"> <span class="input-group-addon"> <span class ...

Remove any nulls or undefined values from the object

I have developed a custom function that eliminates null and undefined values from an object. However, it seems to be mistakenly removing keys where the value is 0 as well. For instance: { key1: 'value1', key2: 0 } Even though it shouldn&ap ...

Is it possible to retrieve JavaScript object properties using HTML elements?

I have fetched an array of objects using jQuery.getJSON(). Each object should be represented by an HTML div element, allowing users to click on the element and access all properties of the corresponding object. What is the most efficient approach for achie ...

What is the best way to respond to a hashchange event within AngularJs?

I am new to AngularJs and I am trying to update the page on hashchange events. Currently, I have this code which I know is not the proper way to do it: <!DOCTYPE html> <html> <head> <style> #hashdrop { display:block; ...

Apologies, the system encountered an issue while trying to access the "name" property which was undefined. Fortunately, after refreshing the page, the error was successfully resolved

When the profile route is accessed, the code below is executed: import React, { useState, useEffect } from 'react' import { Row, Col, Form, Button } from 'react-bootstrap' import { useDispatch, useSelector } from 'react-redux' ...

Leveraging Prototype's Class creation function to declare confidential and safeguarded attributes and functions

Looking for a solid approach to defining private and protected properties and methods in Javascript? Check out this helpful discussion here on the site. Unfortunately, the current version of Prototype (1.6.0) doesn't offer a built-in method through it ...

AngularJS - Move the <li> element to the top when its corresponding checkbox is selected

This particular question pertains to a topic that was previously discussed in another thread The scenario involves using a ng-repeat as shown below: <li ng-repeat="opt in namesCtrl.uniqueCars"> <input type="checkbox" ng-model="namesCtrl.filt ...

Is there a shared instance for regular expressions created using expression literals?

In the book "Javascript: The Good Parts" by Crockford, there is a code snippet that highlights how RegExp objects created using regular expression literals share a single instance: function create_matcher() { return /a/gi; } var x = create_matcher(); ...

SSL certificate not being presented by the Socket.io chat server

I recently discovered that the chat feature in an application I developed a while ago is not working after switching the website from http to https. It seems like I need to SSL my Socket.io chat socket to avoid browser errors. However, when I try to conne ...

Can you clarify the concept of closures and how they bind the loop counter to the function scope?

I have observed programmers setting up event listeners inside loops, utilizing the counter. The syntax that I have come across is as follows: for(var i=0; i < someArray.length; i++){ someArray[i].onclick = (function(i){/* Some code using i */})(i); ...

Managing dynamically loaded scripts in Meteor.js

This poses an interesting query: is there a way to regulate which scripts a client is provided with? I've partitioned my code into dynamically loadable segments using the import('dynamically_loadable_file') method, but each time it's ca ...

Javascript callback function

Greetings everyone! I've developed a simple nodesjs server using express. The server includes a login page where users enter their credentials to be checked against an Sqlite3 DB. My concern lies in the fact that the callback function only executes on ...

Nuxt Page Featuring One Exclusive Product

I am just getting started with Nuxt and I'm in the process of creating a Single Product. I have some questions: How can I generate multiple pages using SSR and create a unique HTML for each page? Should CSR be developed first before implementing SSR, ...

Discover the ins and outs of crafting a tooltip in a spreadsheet with Java-Jsp

Seeking assistance on how to incorporate a tooltip or comment feature in a spreadsheet similar to the one found in Google Spreadsheets (right-click and insert comment). For example: ![tooltip] https://sites.google.com/a/wongsk.twbbs.org/wongsk/image2/pop ...

Is there an Angular counterpart to Vue's <slot/> feature?

Illustration: Main component: <div> Greetings <slot/>! </div> Subordinate Component: <div> Planet </div> Application component: <Main> <Subordinate/> </Main> Result: Greetings Planet! ...

Crafty Checkbox Selector [ leveraging jquery ]

I have created some fake checkboxes using elements like <span> after the real checkbox and they are working fine! However, I am having trouble counting the checked checkboxes when a checkbox is clicked. I have tried using methods like: $(".elm:chec ...

What are the steps for activating a textbox in a specific row?

I am attempting to activate a textbox by clicking on the corresponding button, but whenever I click any button, it always activates the first textbox. I prefer not to use 'id' in this scenario. <%@page contentType="text/html" pageEncoding="UT ...

I am experiencing difficulty getting Bootstrap Columns to appear next to each other despite trying numerous solutions

Check out this code snippet: <div class="mainptext"> <h3><strong>Master the following:</strong></h3> <div class="container"> <div class="row"> <div class ...