Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing ArrayAdapter optgroup children data binding #6310

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

5andr0
Copy link

@5andr0 5andr0 commented May 7, 2024

ArrayAdapter.convertToOptions fails to create item data for optgroup children, not binding it to the select options.
This results in a bug, where the passed data element to select(data) is not initialized and normalized, thus element is null and id is an integer. Therefore the select function can't find the corresponding <option> while comparing an integer id with string <option>[value] and creates duplicate options when selecting optgroup child options, which was meant for adding search tags:

ArrayAdapter.prototype.select = function (data) {
  var $option = this.$element.find('option').filter(function (i, elm) {
    return elm.value == data.id.toString();
  });

  if ($option.length === 0) {
    $option = this.option(data);

    this.addOptions($option);
  }

Here's a polyfill for the bugfix

$.fn.select2.amd.require(['select2/data/array'],
  function (ArrayAdapter) {
    let __super__convertToOptions = ArrayAdapter.prototype.convertToOptions;
    ArrayAdapter.prototype.convertToOptions = function (data) {
      var self = this;

      const $options = __super__convertToOptions.call(this, data);
      for(const $option of $options) {
        (function applyChildData(option) {
          if (option.children) {
            option.children.forEach(function(child, index, children) {
              var $child = $($(option.element).children()[index]);
              children[index] = self.item($child);
              applyChildData(children[index]);
            });
          }
        })(self.item($option));
      }
      return $options;
    }

    ArrayAdapter.prototype.select = function (data) {
      if (!data.element) {
        this.addOptions(this.option(data));
      }
  
      ArrayAdapter.__super__.select.call(this, data);
    };
  }, null, true);

This pull request includes a

  • Bug fix
  • New feature
  • Translation

The following changes were made

  • Creating a data cache for each optgroup child (recursively for nested optgroups) and binding it correctly to its corresponding select option
  • simplifying the search if there exists an option corresponding to the data passed to select, also making it available for optgroups and not only options.

ArrayAdapter.convertToOptions fails to create item data for optgroup children, not binding it to the select options.  
This results in a bug, where the passed data element to select(data) is not initialized and normalized, thus element is null and id is an integer. Therefore the select function can't find the corresponding <option> while comparing an integer id with string <option>[value]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant