Thursday, 14 September 2023

select2 multi group select. Select parent, disable child nodes. Unselect parent, enable child nodes

I have implemented 2 custom functions with select2:

  1. Select parent node, add parent node to selected and disable child nodes.
  2. Unselect parent node, remove from selected and enable child nodes.

This is working, except when adding and removing parent node in this order:

  1. Select parent
  2. Open emerging options (you can see child nodes are disabled)
  3. Click outside search box, so emerging options close
  4. Unselect parent
  5. Open emerging box again (child nodes are still disabled)

On the contrary, it works if step 2 and 3 are not done.

  1. Select parent
  2. Unselect parent
  3. Open emerging options (you can see child nodes are enabled back)

Please see a working example:

const tags = [{
    'id': 1,
    'text': 'Parent 1',
    'children': [{
        'id': 'tag11',
        'text': 'Tag 11'
      },
      {
        'id': 'tag12',
        'text': 'Tag 12'
      }, {
        'id': 'parent1',
        'text': 'Parent 1'
      },
    ],
  },
  {
    'id': 2,
    'text': 'Parent 2',
    'children': [{
        'id': 'tag21',
        'text': 'Tag 21'
      },
      {
        'id': 'tag22',
        'text': 'Tag 22'
      },
      {
        'id': 'parent2',
        'text': 'Parent 2'
      },
    ],
  }
];
$(document).ready(function() {

  const selectField = $('#target');
  
  selectField.select2({
    width: '300px',
    templateResult: function(option) {
      if (option.element && (option.element).hasAttribute('hidden')) {
        return null;
      }
      return option.text;
    }
  });

  selectField.on('select2:open', function(e) {
    let allOptionsStart = this.options;
    $('#select2-target-results').on('click', function(event) {
      let allOptions = [];
      $.each(allOptionsStart, (key, option) => {
        allOptions[option.value] = option;
      });

      const data = $(event.target).html();
      const selectedOptionGroup = data.toString().trim();

      let selectedOptionGroupId = '';
      $.each(tags, (key, tag) => {
        if (selectedOptionGroup.toString() === tag.text.toString()) {
          $.each(tag.children, (key, child) => {
            if (selectedOptionGroup.toString() === child.text) {
              selectedOptionGroupId = child.id;
            }
            const jTag = $(allOptions[child.id]);
            if (Object.keys(jTag).length > 0) {
              if (!jTag[0].hidden) {
                jTag[0].disabled = true;
              }
            }
          });
        }
      });
      $('select').select2({
        width: '300px',
        templateResult: function(option) {
          if (option.element && (option.element).hasAttribute('hidden')) {
            return null;
          }
          return option.text;
        }
      });
      event.stopPropagation();

      let options = selectField.val();
      if (options === null || options === '') {
        options = [];
      }
      options.push(selectedOptionGroupId);

      selectField.val(options);
      selectField.trigger('change'); // Notify any JS components that the value changed
      selectField.select2('close');
    });
  });

  selectField.on('select2:unselecting', function(e) {
    let allOptions = [];
    $.each(this.options, (key, option) => {
      allOptions[option.value] = option;
    });
    const unselectedGroupText = e.params.args.data.text;
    $.each(tags, (key, tag) => {
      if (unselectedGroupText === tag.text) {
        $.each(tag.children, (key, childTag) => {
          const jTag = $(allOptions[childTag.id]);
          if (Object.keys(jTag).length > 0) {
            if (!jTag[0].hidden) {
              jTag[0].disabled = false;
            }
          }
        });
      }
    });
  });

});
li.select2-results__option strong.select2-results__group:hover {
  background-color: #ddd;
  cursor: pointer;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>

<select id="target" data-placeholder="Select an option" multiple='multiple'>
  <optgroup label="Parent 1">
    <option value="tag11">Tag 11</option>
    <option value="tag12">Tag 12</option>
    <option value="parent1" hidden>Parent 1</option>
  </optgroup>
  <optgroup label="Parent 2">
    <option class="tag21">Tag 21</option>
    <option class="tag22">Tag 22</option>
    <option value="parent2" hidden>Parent 2</option>
  </optgroup>
</select>

jsfiddle (just in case): https://jsfiddle.net/ivantxo/bzu2xmp9/151/

Can anyone please help me to see what's wrong?

This should work in both cases.

Thanks.



from select2 multi group select. Select parent, disable child nodes. Unselect parent, enable child nodes

No comments:

Post a Comment