Изменение observableArray не приводит к немедленному обновлению выбранного пользовательского интерфейса. - PullRequest
0 голосов
/ 26 апреля 2020

У меня есть выпадающий список. Если пользователь выбирает параметр all, я хочу, чтобы все остальные параметры были отменены, и выберите только all. У меня это почти работает, но моя проблема в том, что select не показывает обновленное значение, пока не минимизировать выпадающий список. Состояние observableArray представляется правильным.

Вот HTML:

<select data-bind="options: games, selectedOptions: selectedGame, optionsText: 'name', optionsValue: 'id'" multiple="true"></select>

И javascript:

this.games= [
{ 
    name: 'All',
    id: 'all'
}, 
{ 
    name: 'Game1',
    id: 'game1'
},
{ 
    name: 'Game2',
    id: 'game2'
},  
] 

this.selectedGame = ko.observableArray(['all']);
this.selectedGameBeforeChange = ko.observableArray([]);

this.selectedGame.subscribe((oldValue) => 
{
    this.selectedGameBeforeChange(oldValue);
}, null, 'beforeChange');

this.selectedGame.subscribe((newValue) => 
{
    const newValueAdded = newValue.filter(x => !this.selectedGameBeforeChange().includes(x));
    if (newValueAdded.length > 0 && newValueAdded[0] === 'all'){
        this.selectedGame.removeAll();
        this.selectedGame.push('allCombined');    
    }

    this.updateTable();
});

приведенный выше код работает, но изменение отражается в пользовательском интерфейсе только после того, как я «свернул» выбор и снова открыл его. Есть ли способ принудительно обновить пользовательский интерфейс, как только мой observableArray будет обновлен?

1 Ответ

0 голосов
/ 28 апреля 2020

У вас есть 2 ошибки:

  1. Вместо push('allCombined') должно быть push('all').
  2. Работает, когда all выбран последним, но не когда он выбран в качестве первого варианта. Чтобы это исправить, нам нужно немного изменить условие.

Вот окончательный код (с несколькими незначительными изменениями, например, с использованием self вместо this):

var vm = function () {
  var self = this;
  self.games = [
    { name: 'All', id: 'all' }, 
    { name: 'Game1', id: 'game1' },
    { name: 'Game2', id: 'game2' }  
  ]; 
  self.selectedGames = ko.observableArray(['all']);
  self.selectedGamesBeforeChange = ko.observableArray([]);

  self.selectedGames.subscribe((oldValue) => 
  {
      self.selectedGamesBeforeChange(oldValue);
  }, null, 'beforeChange');

  self.selectedGames.subscribe((newValue) => 
  {
      if (newValue.length > 1 && 
          newValue.includes('all')){
          self.selectedGames.removeAll();
          self.selectedGamesBeforeChange.removeAll();
          self.selectedGames.push('all'); 
      }
  });
};
ko.applyBindings(new vm());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select data-bind="options: games, selectedOptions: selectedGames, optionsText: 'name', optionsValue: 'id'" multiple="true"></select>
...