在 Knockout-bound 下拉列表中显示值而不是文本

Show value instead of text in Knockout-bound dropdown

我有一个 HTML 下拉菜单,我在其中使用 Knockout.js 来绑定选项。通过下拉菜单,您可以 select ISO 国家/地区代码。在(短)下拉列表中,我想将两个字母的国家/地区代码显示为文本。国家的全名应该只在用户打开下拉菜单时出现。类似于:

+=======+===+
| DE    | v |
+=======+===+
| Germany   |
| England   |
| France    |
| Spain     |
| USA       |
+-----------+

现在,我的 HTML 代码如下所示:

<select class="form-control w-25" data-bind="
    value: customAddress.country,
    options: countryList,
    optionsText: 'name',
    optionsValue: 'code',
    optionsCaption: 'Country'
" required></select>

显然,如果您select,下拉菜单现在显示"Germany"。我发现了一些想法,可以在 onBlur 事件中使用 jQuery 替换下拉菜单的显示文本。但我担心,这会干扰 knockout 的数据绑定机制(所有属性都是可观察的)。

我该如何解决?我需要自定义绑定吗?

您不一定需要自定义绑定处理程序(当然也不需要求助于 jQuery);这可以使用默认绑定处理程序来完成。

  1. 将 select 菜单状态 (open/closed) 存储在一个变量中;
  2. 使用 event 绑定在 blur/focus 事件上切换此变量。如果是 focus 事件,我们假设菜单是打开的;如果是 blur 事件,我们假设菜单已关闭。
  3. 将函数传递给 optionsText,该函数将 return 代码或国家/地区,具体取决于所述变量的值。

JS:

function ViewModel() {
  var vm = this;

  vm.countries = [{
      code: 'DE',
      country: 'Germany'
    },
    {
      code: 'NL',
      country: 'The Netherlands'
    },
    {
      code: 'BE',
      country: 'Belgium'
    }
  ];

  vm.countrySelectIsOpen = ko.observable(false);
  vm.selectedCountry = ko.observable();

  vm.getOptionsText = function(item) {
    return item[vm.countrySelectIsOpen() ? 'country' : 'code'];
  }

  vm.toggleCountrySelectStatus = function(data, event) {
    vm.countrySelectIsOpen(event.type === 'focus');
  }
}

ko.applyBindings(new ViewModel)
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<select class="form-control" data-bind="
        options: countries,
        optionsText: getOptionsText,
        optionsValue: 'code',
        optionsCaption: 'Country',
        value: selectedCountry,
        event: {
            blur: toggleCountrySelectStatus,
            focus: toggleCountrySelectStatus
        }
    "></select>

Fiddle: https://jsfiddle.net/thebluenile/hf70kg84/