“全选”选项未作为 TomSelect 下拉列表中的第一项出现

问题描述 投票:0回答:1

我正在使用 TomSelect 在我的项目中创建一个多选下拉列表。我添加了“全选”选项,并试图确保它始终显示为下拉列表中的第一项。然而,尽管我做出了努力,“全选”选项并不总是出现在列表顶部。

这是我当前的实现:

function renderOptionItem(item, escape) {
  let img = item.src ? `<img class="me-2 tomselect-image" src="${escape(item.src)}" alt="icon" />` : '';
  let subtext = item.subtext ? `<div class="text-muted">${escape(item.subtext)}</div>` : '';
  return `<div class="d-flex align-items-center">
        ${img}
        <div>
        <div>${escape(item.text)}</div>
        ${subtext}
        </div>
      </div>`;
}

function updateSelectedItemsLabel(tomSelectInstance) {
  const selectedItems = tomSelectInstance.getValue();
  const selectedCount = selectedItems.length;
  const control = tomSelectInstance.control.querySelector('.items');

  if (selectedCount > 3 && control) {
    // Clear the control and add the summary item
    control.innerHTML = `<div class="item">Valgt ${selectedCount} elementer</div>`;
  } else {
    tomSelectInstance.refreshItems(); // Refresh to show actual selected items
  }

  // Update the "Select all" checkbox state
  const selectAllCheckbox = tomSelectInstance.dropdown_content.querySelector('.option[data-value="select-all"] input[type="checkbox"]');
  if (selectAllCheckbox) {
    const allItemValues = Object.keys(tomSelectInstance.options).filter(value => value !== 'select-all');
    selectAllCheckbox.checked = selectedItems.length === allItemValues.length;

    // Set a specific ID to the checkbox
    selectAllCheckbox.id = 'groupSelect-opt-0'; // Replace 'your-specific-id' with the desired ID
  }
}

function handleSelectAll(tomSelectInstance) {
  const allItems = tomSelectInstance.options;
  const allItemValues = Object.keys(allItems).filter(value => value !== 'select-all');
  const selectedItems = tomSelectInstance.getValue();

  if (selectedItems.length === allItemValues.length) {
    tomSelectInstance.clear(); // Deselect all if already selected
  } else {
    tomSelectInstance.setValue(allItemValues); // Select all
  }
}

function initializeTomSelect(selector, isSingleSelect = false) {
  const tomSelectInstance = new TomSelect(selector, {
    valueField: 'value',
    labelField: 'text',
    searchField: ['text', 'subtext'],
    render: {
      option: (item, escape) => {
        if (item.value === 'select-all') {
          return `<div class="d-flex align-items-center option">
                <div>Vælg alle</div>
              </div>`;
        } else {
          return renderOptionItem(item, escape);
        }
      },
      item: renderOptionItem
    },
    plugins: {
      'remove_button': {},
      'dropdown_input': {},
      'checkbox_options': {},
      'clear_button': {
        title: 'Ryd valgte' // Danish for "Clear selected"
      },
    },
    maxItems: isSingleSelect ? 1 : null,
    placeholder: isSingleSelect ? 'Vælg en mulighed...' : 'Vælg nogle muligheder...',
    create: false,
    allowEmptyOption: false, // Disallow empty options
    onInitialize: function() {
      if (isSingleSelect) {
        this.clear(); // Ensure no default selection
      }
      updateSelectedItemsLabel(this);

      // Add "Select all" option first
      this.addOption({ value: 'select-all', text: 'Vælg alle' });
      this.refreshOptions(false);

      // Ensure "Select all" is the first item
      const dropdownContent = this.dropdown_content;
      const selectAllOption = this.getOption('select-all');
      if (selectAllOption) {
        dropdownContent.insertBefore(selectAllOption, dropdownContent.firstChild);
      }

      dropdownContent.addEventListener('click', (event) => {
        const optionElement = event.target.closest('.option');
        if (optionElement && optionElement.getAttribute('data-value') === 'select-all') {
          event.stopPropagation(); // Prevent the dropdown from closing
          handleSelectAll(this);
          updateSelectedItemsLabel(this);
        }
      });
    },
    onItemAdd: function(value) {
      if (value !== 'select-all') {
        updateSelectedItemsLabel(this);
      }
    },
    onItemRemove: function() {
      updateSelectedItemsLabel(this);
    }
  });

  function moveSelectAllToTop(instance) {
    const dropdownContent = instance.dropdown_content;
    const selectAllOption = instance.getOption('select-all');
    if (selectAllOption) {
      dropdownContent.insertBefore(selectAllOption, dropdownContent.firstChild);
    }
  }

  // Handle the clear button functionality
  tomSelectInstance.on('clear', function() {
    tomSelectInstance.refreshItems();
  });

  // Handle changes to re-enable item removal if more than 3 selected
  tomSelectInstance.on('change', function() {
    const selectedItems = tomSelectInstance.getValue();
    const control = tomSelectInstance.control.querySelector('.items');

    if (selectedItems.length <= 3 && control && control.innerHTML.includes('elementer')) {
      tomSelectInstance.refreshItems(); // Refresh to show actual selected items
    }

    // Update the "Select all" checkbox state
    const selectAllCheckbox = tomSelectInstance.dropdown_content.querySelector('.option[data-value="select-all"] input[type="checkbox"]');
    if (selectAllCheckbox) {
      const allItemValues = Object.keys(tomSelectInstance.options).filter(value => value !== 'select-all');
      selectAllCheckbox.checked = selectedItems.length === allItemValues.length;
    }
  });
}

// Initialize Tom Select elements
document.addEventListener('DOMContentLoaded', function() {
  initializeTomSelect('#employeeSelect');
  initializeTomSelect('#entryTypeSelect', true); // Set isSingleSelect to true for entryTypeSelect
});

问题 尽管有上面的代码片段,“全选”选项并不总是显示为下拉列表中的第一项。我尝试过以下方法:

  1. 首先使用 this.addOption 添加“全选”选项。
  2. 使用以下命令手动将“全选”选项移动到顶部 插入之前。

但是,这些方法并不总是导致“全选”选项位于顶部。

预期行为 每当打开下拉列表时,“全选”选项应始终显示为下拉列表中的第一项。

请求帮助 我正在寻找有关如何确保“全选”选项始终出现在下拉列表顶部的指南。任何有关如何实现这一目标的见解或建议将不胜感激。

javascript tom-select
1个回答
0
投票

为了确保“全选”选项始终显示为 TomSelect 下拉列表中的第一项,您应该在初始化期间以及刷新选项时处理其位置。这是基于现有代码的简化方法:

初始化(onInitialize函数):

使用 this.addOption() 方法添加“全选”选项。 立即使用 this.refreshOptions(false) 刷新选项以反映新添加的内容。 使用 insertBefore() 将“全选”选项移动到下拉内容的顶部。 将“全选”移至顶部功能:

定义一个函数(moveSelectAllToTop)以确保“全选”选项始终位于下拉内容的第一位。 在初始化期间以及刷新选项时调用此函数(onInitialize和refreshOptions)。 您可以通过以下方式调整代码来实现此目的:

 function initializeTomSelect(selector, isSingleSelect = false) {
  const tomSelectInstance = new TomSelect(selector, {
    // Your existing configuration...

    onInitialize: function() {
      if (isSingleSelect) {
        this.clear(); // Ensure no default selection
      }
      
      // Add "Select all" option and ensure it's at the top
      this.addOption({ value: 'select-all', text: 'Vælg alle' });
      this.refreshOptions(false); // Refresh options immediately
      
      moveSelectAllToTop(this); // Ensure "Select all" is the first item

      // Other initialization logic...
    },

    // Other event handlers...

    onItemAdd: function(value) {
      if (value !== 'select-all') {
        updateSelectedItemsLabel(this);
      }
    },

    onItemRemove: function() {
      updateSelectedItemsLabel(this);
    }
  });

  // Function to move "Select All" to the top of dropdown content
  function moveSelectAllToTop(instance) {
    const dropdownContent = instance.dropdown_content;
    const selectAllOption = instance.getOption('select-all');
    if (selectAllOption) {
      dropdownContent.insertBefore(selectAllOption, dropdownContent.firstChild);
    }
  }

  // Additional event listeners and handlers...

  // Initialize TomSelect instance
  // Ensure proper initialization for all instances
}

// Initialize Tom Select elements
document.addEventListener('DOMContentLoaded', function() {
  initializeTomSelect('#employeeSelect');
  initializeTomSelect('#entryTypeSelect', true); // Set isSingleSelect to true for entryTypeSelect
});

说明:

onInitialize 函数:当 TomSelect 实例初始化时,添加“全选”选项并立即刷新选项(refreshOptions(false))。然后,您调用 moveSelectAllToTop(this) 以确保该选项位于顶部。

moveSelectAllToTop 函数:该函数使用insertBefore()将“全选”选项移动到下拉内容(dropdownContent)的顶部。它检查选项是否存在(getOption('select-all')),然后将其放置在 dropdownContent 中的第一个子元素之前。

通过以这种方式构建初始化和选项管理,您可以确保“全选”选项在打开或刷新时始终显示为下拉列表中的第一项。此方法应该可以解决您在 TomSelect 下拉列表中定位“全选”选项时遇到的问题。

© www.soinside.com 2019 - 2024. All rights reserved.