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

Display the date in the user interface grid table

I've integrated ui-grid in my project to showcase data along with dates. An example of a date fetched from an ajax call would be: DateReview='06/25/2016' The current format being mm/dd/yyyy for display purposes. The column definition in ...

Make real-time edits to JavaScript code on a webpage

Is there a method aside from using Firebug in the DOM view to edit live JavaScript embedded within an HTML page? For example, code like this within a .html file: <script type="text/javascript> // code here </script> Thank you. ...

Progressing in a connected sequence of changes on a linear graph with distinct points and a pause

A jsfiddle has been created here. Looking to move a circle along a sine wave graph, triggered by a click event. The circle should stop at specific x and y value pairs on the graph before moving to the last point and looping back to the first (ideally unti ...

What are the steps to downloading a server-generated image with user data from the client using Express?

I am facing a challenge with downloading a server-generated image immediately after it is created. My current approach involves using fetch to send user input data (bypassing HTML forms). Although the image is successfully generated on the server, I am str ...

Tips for distinguishing between the different values

Greetings! I am currently utilizing this code snippet to retrieve values from a Java class. Upon getting the data from Java, it triggers an alert displaying two values separated by spaces. My next goal is to split the values into two separate entities an ...

Stop the slider when a video pops up

Years ago, I had a slider created for me that supports both images and video with a timer. However, the issue I'm facing is that when the timer runs every 10 seconds, the video gets cut off if it's not finished playing. Below is the json file st ...

I am unsure of the process for implementing an OnClick event to modify the colors of a square

Seeking guidance from the more experienced individuals here as I am just starting out. Any help would be greatly appreciated! This might seem simple to many of you, but for me it's quite challenging. This is how my HTML code looks: <html> < ...

Assess the iOS app on Meteor to establish a live connection with an authentic server (not the local host)

Testing my Meteor application on an iOS phone has been a learning experience. Following the steps outlined in this guide, I initially deployed the app with the commands: meteor install-sdk ios meteor add-platform ios meteor run ios meteor run ios-dev ...

Utilize jQuery post to send a request to a particular function located at a given URL

Is there a way to accomplish the following: $.post( "functions.php", { name: "John", time: "2pm" }) .done(function( data ) { alert( "Data Loaded: " + data ); }); Instead, is it possible to direct your data to a particular function in "functions.p ...

Tips for integrating an arrow function as a property in a functional programming approach using JavaScript or TypeScript

Suppose I were to create a constructor for a functional class with TypeA as an argument, and TypeB representing the type of the class itself. In such cases, I can implement it using: functionName(argument: TypeA): TypeB { this.property = argument; ...

What could be causing my express router.get endpoints with multiple paths to only render text?

Currently, I am in the process of configuring a password reset flow using Pug (formerly Jade) and Express. Oddly enough, GET requests that contain URLs with multiple appended paths are causing my Pug view files to render with only text. The images and sty ...

What is the best way to filter two tables using only one search bar?

In my Vue2 application, I have implemented a pair of data tables on one of the pages. Each table is placed behind a tab, allowing users to choose which one they want to view. The search bar, however, is not confined within a tab as I wanted to avoid duplic ...

When the user saves the changes on the pop-up window, the main window will automatically refresh

I currently have a calendar feature that allows users to create, edit, and delete appointments. When a user clicks on the new appointment button, it opens a window above the calendar interface. Once the user fills out the necessary fields and clicks save, ...

Reveal Password Feature in Angular After User Click

I am working on an inventory page that includes a password field. My goal is to initially hide the password and display it as points (****) instead. I would like the password to be revealed either when clicked or through a pop-up. JS var retrieveCert ...

Reorganizing objects upon insertion in Mongo DB

I am encountering an issue in my Node.js app where MongoDB is causing objects to be reordered when inserting new records into the database. I am using the following insert method: collection.insert(object, {safe:true}, function(err, result) { if (err) ...

when passing a JavaScript symbol in Django's JSON objects, it does not display properly

When working with Django (2.2), my goal is to send a JSON response in this format: return JsonResponse(data, safe=False) Within the data object, there is a value that looks like this: "unit": "\u33A5" (cubic meters). However, ...

What is the syntax for requesting a JSONArray in an Ajax call using jQuery?

After browsing through numerous resources like this, this, and this, I finally landed on this. The main objective is to iterate over the JSON data returned from an Ajax call, which is encoded using json_encode in PHP. When I inspect the object using cons ...

When implementing a v-for loop in Vue.js with Vuetify and using v-dialog components, the click event may be overwritten for all v-dialogs except

My app features the utilization of a Vuetify v-dialog within a v-for loop. However, I am encountering an issue where clicking on any chip within the loop triggers the click event for the last v-chip, instead of the specific one being clicked. It appears t ...

Storing data in Angular service for future use

My ui-grid is functioning correctly, utilizing server side pagination with a view button to display row details on a separate page. However, upon returning to the grid after viewing details, it defaults back to displaying the first page. I would like it to ...

Modifying the Position of the Search Box within DataTables by Manipulating DOM Elements

As a newcomer to the jQuery datatables plugin, I am still learning how to use it effectively. I have connected the plugin to my tables using the following code: $(document).ready(function() $('#table_id').dataTable({ }); }); ...