Select2 templateResult data has no element to reference

10,283

templateResult is used to create the dom. You can't access the dom before creating it.

Maybe you need something like this:

(Append the value of "data-appendme" to the option's text in createTag)

<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>test</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <!DOCTYPE html>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
</head>

<body>
    <link rel="stylesheet" href="style.css">
    <script src="index.js"></script>
    <select class="custom-dropdown freeform" data-appendme="blorg"></select>
    <script>
        $('.custom-dropdown').each(function () {
            var $select = $(this);
            $select.css('width', '100%');
            if ($select.hasClass('freeform')) {
                $select.select2({
                    tags: true,
                    createTag: function (params) {
                        return {
                            id: params.term,
                            text: params.term + $select.data('appendme'),
                            newOption: true
                        }
                    },
                    templateResult: function (data, container) {
                        var $result = $("<span></span>");
                        $result.text(data.text);
                        return $result;
                    },
                    placeholder: "Press ENTER for list of options",
                    allowClear: true,
                    selectOnClose: true
                });
            } else {
                $(this).select2({
                    placeholder: "Press ENTER for list of options",
                    allowClear: true,
                    selectOnClose: true,
                });
            }

            $(this).on('select2:select', function (e) {
                if (e.params.data.text != '') {

                    var id = $(this).attr('id');
                    var select2 = $("span[aria-labelledby=select2-" + id + "-container]");
                    select2.removeAttr('style');
                }
            });
            $(this).on('select2:close', function () {
                $(this).focus();
            });
        });

    </script>
</body>

</html>

If you don't want the "blorg" in options but want it in the select tag, you can replace it with an empty string in templateResult.

Share:
10,283
Alex
Author by

Alex

Updated on June 08, 2022

Comments

  • Alex
    Alex almost 2 years

    I'm attempting to append text to any new value added in a select2 with freeform text option. The text appended I want to set on the select element (in my case by way of an mvc helper).

    The issue is that the data coming into the templateResult doesn't have an element. Everywhere I've searched, data.element is used to get into the DOM, but it's not there for me and I'm not sure why. If I look in the createTag function the params also has no element. Also the container is just an "li" apparently not yet in the dom, no children or parents.

    Here is code:

    $('.custom-dropdown').each(function() {
      $(this).css('width', '100%');
      if ($(this).hasClass('freeform')) {
        $(this).select2({
            tags: true,
            createTag: function(params) {
              return {
                id: params.term,
                text: params.term,
                newOption: true
              }
            },
            templateResult: function(data, container) {
              var $result = $("<span></span>");
    
              $result.text(data.text);
    
              if (data.newOption) {
                //data.element is undefined here!!!
              }
            }
    
            return $result;
          },
          placeholder: "Press ENTER for list of options",
          allowClear: true,
          selectOnClose: true
        });
    } else {
      $(this).select2({
        placeholder: "Press ENTER for list of options",
        allowClear: true,
        selectOnClose: true,
      });
    }
    
    $(this).on('select2:select', function(e) {
      if (e.params.data.text != '') {
    
        var id = $(this).attr('id');
        var select2 = $("span[aria-labelledby=select2-" + id + "-container]");
        select2.removeAttr('style');
      }
    
    }); $(this).on('select2:close', function() {
      $(this).focus();
    });
    
    });
    

    An example of the select would be:

    select class="custom-dropdown freeform" data-appendme="blorg"

  • Alex
    Alex over 6 years
    Thanks, that did the trick with a small modification. The templateResult checking for data.newOption is unnecessary since the text comes in already ready to be set, and it eliminates all the existing dropdown items since they aren't set for newOption. So just removing that if block and returning $result there is perfect.
  • beaver
    beaver over 6 years
    @blackmiaool, why when I type the first char a new tag is immediately created (and selected)?