Show various columns in Select2

I am currently utilizing select2 and I am interested in displaying a multicolumn table as a dropdown. In order to achieve this, the width of the drop-down container should differ (be larger) than the input itself.

Is it feasible to accomplish this?

Furthermore, I would like to present a table with multiple columns. Upon reviewing the movies example, I observed that a new table is created for each row within the formatResult function.

Would it be viable to have every row included in the same table so that all cells possess equal width? Perhaps I need to establish a template to house the rows or something similar.

My objective is to have a compact input display the code of an entity while a spacious dropdown reveals additional columns.

--

For further information, please refer to this related issue on Github: https://github.com/ivaynberg/select2/issues/1314

Answer №1

formatresult was not effective for my situation. However, templateResult works perfectly when incorporating data from PHP into HTML generated content (not via ajax).

Here is the code that worked for me, where I divide my columns using a pipe character (there could be more than 2 columns):

html (from PHP) :

<option value="...">
    column 1 text | column 2 text
</option>

javascript (jQuery) :

$('#selectSubstance').select2({
    templateResult: function(data) {
        var r = data.text.split('|');
        var $result = $(
            '<div class="row">' +
                '<div class="col-md-3">' + r[0] + '</div>' +
                '<div class="col-md-9">' + r[1] + '</div>' +
            '</div>'
        );
        return $result;
    }
}); 

EDIT 2021-06-28

If you want the same visual for the selected item (closed select), use the identical syntax with templateSelection:

For instance:

$('#selectProduct').select2({            
    placeholder: 'Choose a product.',
    templateResult: function(data) {
        var r = data.text.split('| ');
        var result = jQuery(
            '<div class="row">' +
                '<div class="col-md-3">' + r[0] + '</div>' +
                '<div class="col-md-9">' + r[1] + '</div>' +
            '</div>'
        );
        return result;
    },
    templateSelection: function(data) {
        var r = data.text.split('| ');
        var result = jQuery(
            '<div class="row">' +
                '<div class="col-md-3">' + r[0] + '</div>' +
                '<div class="col-md-9">' + r[1] + '</div>' +
            '</div>'
        );
        return result;
    }
});

Answer №2

For those using Select2 version 3.5, the following workaround can be implemented:

function formatResultMulti(data) {
  var city = $(data.element).data('city');
  var classAttr = $(data.element).attr('class');
  var hasClass = typeof classAttr != 'undefined';
  classAttr = hasClass ? ' ' + classAttr : '';

  var $result = $(
    '<div class="row">' +
    '<div class="col-md-6 col-xs-6' + classAttr + '">' + data.text + '</div>' +
    '<div class="col-md-6 col-xs-6' + classAttr + '">' + city + '</div>' +
    '</div>'
  );
  return $result;
}

$(function() {
  $('#multi').select2({
    width: '100%',
    formatResult: formatResultMulti
  });
})
body{
  background-color: #455A64;
}

#multiWrapper {
  width: 300px;
  margin: 25px 0 0 25px;
}

.def-cursor {
  cursor: default;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.0/select2.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.0/select2.min.js"></script>
<div id='multiWrapper'>
  <select id="multi">
    <optgroup class='def-cursor' label='Country' data-city='City'>
      <option data-city="Athens" id="1" selected>Greece</option>
      <option data-city="Rome" "id="2 ">Italy</option>
  <option data-city="Paris " "id="3">France</option>
    </optgroup>
  </select>
</div>

Answer №3

If you're looking for a solution that incorporates Select2 v4 tableish styling and multicolumn search using local JSON data, you've come to the right place.

Here's a brief explanation of how it all comes together:

There are two key functions at play here: the matcher function and the formatSelect function.

The matcher function handles the query by checking each word in the query against the rows to find any matches. It currently returns any row that matches at least one word from the query.

Once the matcher has identified all matching rows (or all rows when there is no query), the formatSelect function steps in. It adds header columns on the first row of data if it's the initial row being rendered.

In terms of structure, this table utilizes bootstrap column widths for layout.

Below is the code snippet:

var firstEmptySelect = true;

function formatSelect(result) {
    // Code logic goes here
}

function matcher(query, option) {
   // Code logic goes here
}

$('#selectAccountDeal').select2({
    data: {!! $deals !!},
    width: '100%',
    templateResult: formatSelect,
    templateSelection: formatSelect,
    escapeMarkup: function(m) { return m; },
    matcher: matcher
})

Example JSON data used:

[{
    "text": "JL - o yea - Testing this deal",
    "id": 4,
    "client_name": "JL",
    "account_name": "o yea",
    "deal_name": "Testing this deal"
}, {
    "text": "JL - test - fj;askld fj",
    "id": 3,
    "client_name": "JL",
    "account_name": "test",
    "deal_name": "fj;askld fj"
}]

HTML for select element:

<select id="selectAccountDeal" name="account_deal_id" placeholder="Select your Deal" required>
  <option></option>
</select>

Visual representation of the select2 dropdown:

https://i.stack.imgur.com/6NFBq.png

Answer №4

I have been experimenting with creating a fixed header row above the columns in order to function as a standard table header row. While I haven't had much success with that yet, I came across a helpful feature request on Github by user trebuchetty which suggested using bootstrap's grid styles like col-md-6 (for bootstrap versions >= 3).

After implementing the suggestion from the Github post, I found that the following select2 options yielded positive results:

formatResult: function(result) {
    return '<div class="row">' +
           '<div class="col-md-6">' + result.name + '</div>' +
           '<div class="col-md-6">' + result.manager + '</div>' +
           '</div>';
},

The variable result in the code snippet represents an element within the array of items displayed in the dropdown menu.

Answer №5

Below are the solutions I have for this issue. I am using select2 version 4.0.3.

The final appearance of the presentation can be seen here: select2-dropdown-table.

To begin with, add a header when the select2 dropdown is opened:

    var headerIsAdded = false;
    $('#stock').on('select2:open', function (e) {
        if (!headerIsAdded) {
            html = '<table class="table table-bordered" style="margin-top: 5px;margin-bottom: 0px;">\
                <tbody>\
                <tr>\
                    <td width="20%"><b>药品名称</b></td>\
                    <td width="10%"><b>成本价</b></td>\
                    <td width="20%"><b>供应商</b></td>\
                    <td width="10%"><b>批号</b></td>\
                    <td width="20%"><b>有效期</b></td>\
                    <td width="20%"><b>库存数量</b></td>\
                </tr >\
                </tbody>\
                </table>';
            $('.select2-search').append(html);
            $('.select2-results').addClass('stock');
            headerIsAdded = true;
        }
    });

Next step

templateResult: function (repo) {
            if (repo.medicine) {
                var html = '<table class="table table-bordered" style="margin-bottom: 0px;">\
                <tbody>\
                <tr>\
                    <td width="20%">' + repo.medicine.name + '</td>\
                    <td width="10%">' + repo.costPrice + '</td>\
                    <td width="20%">' + repo.vendor + '</td>\
                    <td width="10%">' + repo.batchNum + '</td>\
                    <td width="20%">' + repo.expiredDate + '</td>\
                    <td width="20%">' + repo.quantity + '</td>\
                </tr >\
                </tbody>\
                </table>';
                return $(html);
            }
        },

The remaining task involves adjusting the css properties:

.stock .select2-results__option {
  padding: 0px 4px;
}

That should cover everything needed in this situation.

Answer №7

Here is an example I created, inspired by Meloman's answer, that might be useful to someone:

// HTML
 <select 
    class="form-control select2" 
    data-col0htmldebut="<div class='col-md-6'>" 
    data-col0htmlfin="</div>" 
    data-col1htmldebut="<div class='col-md-2'>" 
    data-col1htmlfin="</div>" 
    data-col2htmldebut="<div class='col-md-4'>" 
    data-col2htmlfin="</div>">
          <option value="">Select...</option>
          <option value="-1">Text with no column</option>
          <option value="1">Column1__|__Col2__|__Col3</option>
          <option value="2">Column1__|__Col2__|__Col3</option>
 </select>

$("select.select2").select2({
    templateResult: function (data) {
        if (data.element == null) return data.text;


        /**************  Single-column handler **************/

       // __|__ text separator found between each column?
        var arrOptionText = data.text.split('__|__');
        if (arrOptionText.length <= 1) return data.text;


        /**************  Multi-column handler **************/

        // Get the select object
        var objSelect = $("#" + data.element.parentNode.id);

        // Handling 4 columns here
        var arrStyleColStart = [];
        var arrStyleColEnd = [];

        for (var i = 0; i < 4; i++)
        {
            if (objSelect.attr('data-col' + i + 'htmldebut'))   arrStyleColStart.push(objSelect.data("col" + i + "htmldebut"));
            if (objSelect.attr('data-col' + i + 'htmlfin'))     arrStyleColEnd.push(objSelect.data("col" + i + "htmlfin"));
        }

        if (arrOptionText.length != arrStyleColStart.length) return data.text;

        var $htmlResult = '<div class="row">';
        for (var i = 0; i < arrOptionText.length; i++)
        {
            $htmlResult += arrStyleColStart[i] + arrOptionText[i] + arrStyleColEnd[i];
        }
        $htmlResult += "</div>";

        return $($htmlResult);
    },
    templateSelection: function (data) {
        // Display only the first column in the selection.
        return data.text.split('__|__')[0];
    }
});

Answer №8

Using SELECT2 Version 4 has been a game-changer for me. Credit goes to the brilliant idea from BrinkDaDrink, which inspired me to make some modifications and streamline the code. Below is a snippet of my sample:

        var firstEmptySelect = true; // Indicates that the header has been created

        function s2FormatResult(item) {

            if (!item.id) {
                // Triggered during a remote query
                firstEmptySelect = true; // Resetting
                return item.text;
            }

            var $container; // Custom template container

            // Creating the header
            if (firstEmptySelect) {

                firstEmptySelect = false;

                $container = $(
                    '<div class="row">' +
                    '<div class="col-xs-3"><b>Product ID</b></div>' +
                    '<div class="col-xs-3"><b>Product Name</b></div>' +
                    '</div>' +
                    '<div class="row">' +
                    '<div class="col-xs-3">' + item.id + '</div>' +
                    '<div class="col-xs-3">' + item.text + '</div>' +
                    '</div>'
                );

            }
            else {
                $container = $('<div class="row">' +
                    '<div class="col-xs-3">' + item.id + '</div>' +
                    '<div class="col-xs-3">' + item.text + '</div>' +
                    '</div>');
            }


          return $container
        }

For a visual representation of this code, click here.

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

Modifying button appearance upon clicking using JavaScript

JavaScript: const buttons = document.getElementsByClassName("togglebtn"); for (let i = 0; i < buttons.length; i++) { buttons[i].onclick = function () { this.classList.toggle("active"); } } html: <md-butt ...

Rendering images in Next.js version 10

Just recently, Next.js version 10 was launched featuring the latest Image element, making it a great asset for websites that heavily rely on images! When I receive an HTML response from the server, it looks something like this: HTML = "<div> &l ...

There seems to be a problem with the bundle.js file caused by Uglify

I've just finished a project and now I'm ready to start building it. Utilizing a boilerplate project, I still find myself struggling to comprehend all the npm/webpack intricacies happening behind the scenes. Whenever I try to run "npm start", I k ...

React function does not provide a return value

In my function, I am calculating the current sum of elements. Within my Api, there is a method called Getcoin that works correctly when I log each element during the foreach cycle. However, I am not getting any results in the return statement or console.lo ...

After installing grunt, the Gruntfile cannot be located. How can this issue be resolved?

After installing grunt, I encountered a problem. Despite trying some commands suggested on stackoverflow in this How to install grunt and how to build script with it, running the grunt command still shows the same result. What steps should I take next?ht ...

Creating a web form with the ability to select multiple images using Javascript

Currently, I am in the process of developing an HTML form that enables users to select an image, a URL, and text that will be inserted as a <li> into a webpage. However, I am facing an issue where I want users to create multiple <li> per input. ...

What is the best way to hide or eliminate spinners/arrows in react-select?

I am currently utilizing react-select for my project, but I'm encountering an issue with removing the spinners/arrows from the dropdown menu. So far, I have successfully removed the default separator "|" and Dropdown Indicator using the following cod ...

React Alert: Unable to update state in an unmounted React component

I have encountered an issue while using Redux in this particular file. When I click on the second component, I receive the following error message: Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it ind ...

Modifying Bracket Shell Name leads to WebSocket Connection Failure

I have been working on developing an application using the Brackets shell. Specifically, I am in the process of creating a customized code editor for a project rather than starting from scratch by modifying Brackets. Up until now, I have managed to addres ...

The error encountered is an unhandled rejection with a message stating "TypeError: Cannot access property 'username' of null

My tech stack includes NodeJS, PassportJS, MySQL, and Sequelize (ORM for MySQL). The following code snippet is taken from my Passport.JS file. Whenever a user registers on my website, an error is returned if the username or email is already in use. If both ...

The Minimax algorithm experiencing issues in Next.js

I recently wrote some code in Next.js, but unfortunately, it's not functioning as expected. Despite my best efforts and attempts at utilizing alpha beta pruning, the code still fails to work properly. The issue lies in the fact that it simply returns ...

Angular-datatables has a scroller function that allows for easy navigation within the content of

I've been scouring the web for hours, but I can't seem to find a solution. Can someone please assist me in resolving this issue? Issue: I integrated angular-datatables within an md-tab using Angular material. Everything was running smoothly unti ...

Ways to prevent false activation of functions due to changes and clicks

I have a text box and a clear button. When the user inputs something in the text box and then clicks out of it, a function called 'validate()' is triggered to perform an action. However, when I click the clear button instead and trigger another f ...

Substitute a JSONP API call using $.ajax() with a direct server-to-server API call

My javascript application utilizes an ajax function that has the following structure: $.ajax({ url: apiURL, dataType: 'jsonp', success: function(data) { if (data.ok) { //perform actions }}}); Everything was working perfectly until I ...

Having trouble closing the phonegap application using the Back Button on an Android device

I've encountered an issue with my code for exiting the application. It works perfectly the first time, but if I navigate to other screens and then return to the screen where I want to close the app, it doesn't work. <script type="text/javascr ...

Executing an Amplifyjs GET request containing a request body

Is it possible to utilize GET requests with a message body using AmplifyJS? Specifically, I am curious about the process of achieving this functionality with AmplifyJS. While synthetic tests function properly (using Fiddler as my test client), I have enc ...

Tips for maintaining interactivity after a page refresh

$(document).ready(function () { $("#2").click(function () { $("#content").load("{% url 'about' %}"); }); $("#3").click(function () { $("#content").load("{% url ...

How to flip the value in v-model using VueJS

Below is the code snippet that I am working with: <input v-model="comb.inactive" type="checkbox" @click="setInactive(comb.id_base_product_combination)" > I am looking to apply the opposite value of comb.inactive to the v-model. Here are m ...

Steps to make pop-up iframe function on the same page within a react nextjs application

My vanilla Html app has a pop-up feature that functions perfectly. When the button is clicked, the pop-up opens and everything works as expected. However, I am encountering an issue when trying to implement this same functionality in my React, NextJS app. ...

Issues with returning undefined values in JSON with Node.js and AngularJS

I have developed an application that communicates with an API to retrieve and display data. The process involves entering a username in the client input, which is then sent to the server. Upon checking, everything seems to be working fine at this stage. H ...