You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为SlickGrid下拉单元格编辑器动态添值并复刻jQuery UI Combobox?

Alright, let's build that jQuery UI Combobox with dynamic option addition—exactly matching Excel's handy Alt+Down Arrow behavior for spreadsheet columns! You mentioned you already have a selection cell editor set up, so we'll extend that to support adding new values that show up in subsequent cells of the same column. Here's how to do it step by step:

1. Refactor Option Storage for Dynamic Updates

First, we need to move away from static comma-separated strings to a column-specific array. This lets us easily add new values and share them across all cells in the same column:

// Initialize a map where keys are your column IDs, values are option arrays
const columnOptions = {
  "target-column-id": ["Option1", "Option2", "Option3"]
};

Replace "target-column-id" with the actual identifier you use for your editable column (like a data-column-id attribute on table cells).

2. Enhance the jQuery UI Combobox Widget

We'll modify the core combobox widget to support inputting new values and updating our shared option array. This is where the magic happens:

$.widget("custom.dynamicCombobox", {
  _create: function() {
    this.wrapper = $("<span>")
      .addClass("dynamic-combobox")
      .insertAfter(this.element);

    this.element.hide();
    this._createAutocomplete();
    this._createDropdownButton();
  },

  _createAutocomplete: function() {
    const self = this;
    const select = this.element;
    const columnId = select.closest("td").data("column-id"); // Grab current column ID

    this.input = $("<input>")
      .appendTo(this.wrapper)
      .attr("title", "")
      .addClass("dynamic-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left")
      .autocomplete({
        delay: 0,
        minLength: 0,
        source: function(request, response) {
          const matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
          // Match existing options, plus the new input if it's not already in the list
          const matchedOptions = $.grep(columnOptions[columnId], item => matcher.test(item));
          const newOptionCandidate = request.term.trim() && !matchedOptions.some(opt => opt.toLowerCase() === request.term.toLowerCase())
            ? [request.term]
            : [];
          response(matchedOptions.concat(newOptionCandidate));
        },
        select: function(event, ui) {
          // Add the selected item to the select if it's a new value
          if (!select.find(`option[value="${ui.item.value}"]`).length) {
            select.append($("<option>").val(ui.item.value).text(ui.item.label));
            columnOptions[columnId].push(ui.item.value);
          }
          select.val(ui.item.value);
          self._trigger("select", event, { item: ui.item.option });
          return false;
        },
        change: function(event, ui) {
          // Handle cases where user enters a value without selecting from autocomplete
          const newVal = $(this).val().trim();
          if (!ui.item && newVal) {
            if (!columnOptions[columnId].includes(newVal)) {
              columnOptions[columnId].push(newVal);
              select.append($("<option>").val(newVal).text(newVal));
            }
            select.val(newVal);
          } else if (!newVal) {
            select.val("");
          }
        }
      });

    // Highlight new values in the autocomplete dropdown
    this.input.data("ui-autocomplete")._renderItem = function(ul, item) {
      const isNew = !columnOptions[columnId].includes(item.label);
      return $("<li>")
        .append(`<div>${item.label}${isNew ? " (new)" : ""}</div>`)
        .appendTo(ul);
    };
  },

  _createDropdownButton: function() {
    const self = this;
    const input = this.input;
    let wasOpen = false;

    $("<a>")
      .attr("tabIndex", -1)
      .attr("title", "Show all options")
      .tooltip()
      .appendTo(this.wrapper)
      .button({
        icons: { primary: "ui-icon-triangle-1-s" },
        text: false
      })
      .removeClass("ui-corner-all")
      .addClass("dynamic-combobox-toggle ui-corner-right")
      .on("mousedown", () => wasOpen = input.autocomplete("widget").is(":visible"))
      .on("click", () => {
        input.trigger("focus");
        wasOpen ? input.autocomplete("close") : input.autocomplete("search", "");
      });
  },

  _destroy: function() {
    this.wrapper.remove();
    this.element.show();
  }
});
3. Integrate with Your Existing Cell Editor

Update your cell initialization code to use our new dynamic combobox, and ensure each cell pulls the latest options from the columnOptions array:

// Example: Initialize editor for a table cell (adjust to match your existing code)
function initEditableCell(td) {
  const columnId = td.data("column-id");
  
  // Build select with current column options
  const select = $("<select>")
    .appendTo(td.empty())
    .append(columnOptions[columnId].map(opt => `<option value="${opt}">${opt}</option>`).join(""));
  
  // Initialize our dynamic combobox
  select.dynamicCombobox();

  // Handle editor cleanup when done (e.g., on cell blur)
  td.on("blur", () => {
    td.text(select.val());
    select.dynamicCombobox("destroy");
  });
}
4. Quick Styling for Excel-like Feel

Add this CSS to make the combobox look more familiar to Excel users:

.dynamic-combobox {
  position: relative;
  display: inline-block;
  width: 100%;
}
.dynamic-combobox-toggle {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  padding: 0 8px;
}
.dynamic-combobox-input {
  width: calc(100% - 30px);
  margin: 0;
  padding: 4px 8px;
  box-sizing: border-box;
}
Key Features You'll Get
  • Shared Dynamic Options: New values added in one cell automatically appear in all subsequent cells of the same column
  • Excel-like Workflow: Click the dropdown button to see all options (just like Alt+Down Arrow)
  • Smart Autocomplete: Suggests existing options and highlights new values you're about to add
  • Seamless Integration: Works with your existing cell editor setup

内容的提问来源于stack exchange,提问作者Chapo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:04:08