Knockout / Select2 удалить выбранные опции из выпадающих опций. Не передавая root модель - PullRequest
1 голос
/ 06 февраля 2020

Итак, у меня есть таблица с двумя выпадающими списками (на строку), которую я использую с нокаутом и выбираю. Я хочу иметь возможность отключить или удалить выбранные параметры, которые уже были выбраны.

Благодаря @Jason Spake я смог разобраться в проблеме из Раскрывающийся список Knockout / Select2 содержит правильные параметры, но теперь ничего не показывает в качестве выбранного . Однако предоставленное решение не было идеальным, потому что я не хочу передавать модель root дочерним моделям. Кто-нибудь сможет помочь придумать решение?

Спасибо!

1 Ответ

2 голосов
/ 06 февраля 2020

Мне удалось собрать другой фрагмент, используя вашу идею из предыдущего вопроса, чтобы использовать атрибут disabled вместо полного удаления элементов. Knockout имеет удобную привязку опций выбора, называемую optionsAfterRender, которая позволяет выполнить некоторую постобработку сгенерированных опций.

ko.bindingHandlers.select2 = {
  init: function(element, valueAccessor, allBindingsAccessor, bindingContext) {
    ko.utils.domNodeDisposal.addDisposeCallback(element,
      function() {
        $(element).select2('destroy');
      });
    var select2 = ko.utils.unwrapObservable(allBindingsAccessor().select2);
    $(element).select2(select2);
  },
  update: function(element, valueAccessor, allBindingsAccessor, bindingContext) {
    var allBindings = allBindingsAccessor();
    if ("value" in allBindings) {
      if ((allBindings.select2.multiple || element.multiple) && allBindings.value().constructor != Array) {
        $(element).val(allBindings.value().split(',')).trigger('change');
      } else {
        $(element).val(allBindings.value()).trigger('change');
      }
    }
    $(element).trigger("change");
  }
};

function BookPossessionTransferVM() {
  var self = this;

  self.AllFromList = ([{ "IsAdult": false, "Name": "Bob", "ID": 38438 }, { "IsAdult": false, "Name": "Gordon", "ID": 54686 }, { "IsAdult": true, "Name": "Bill", "ID": 45645 }, { "IsAdult": false, "Name": "Sue", "ID": 1231 }, { "IsAdult": false, "Name": "Ling", "ID": 123578 }, { "IsAdult": false, "Name": "Ivy", "ID": 78945 }]);
  
  self.AllToList = ([{ "IsAdult": false, "Name": "Adam", "ID": 38438 }, { "IsAdult": false, "Name": "Geoff", "ID": 54686 }, { "IsAdult": true, "Name": "Josh", "ID": 45645 }, { "IsAdult": false, "Name": "Sam", "ID": 1231 }, { "IsAdult": false, "Name": "Ming", "ID": 123578 }, { "IsAdult": false, "Name": "Austin", "ID": 78945 }, { "IsAdult": false, "Name": "Tsz", "ID": 78945 }, { "IsAdult": true, "Name": "Ireylnn", "ID": 78945 }, { "IsAdult": true, "Name": "Isabelle", "ID": 78945 }, { "IsAdult": true, "Name": "Vickey", "ID": 78945 }]); 

  self.PossessionChanges = ko.observableArray([]);
  self.PossessionChanges.push(new PossessionChangeVM(self.PossessionChanges().length + 1));

  self.GetPersonById = function(id) {
    return ko.utils.arrayFirst(self.AllFromList, function(person) {
      return person.ID === ko.unwrap(id);
    });
  }

  self.UsedTo = ko.computed(function() {
    return self.PossessionChanges()
      .filter(function(item) {
        return item.SelectedTo() != undefined;
      })
      .map(function(item) {
        return item.SelectedTo();
      });
  });
  self.UsedFrom = ko.computed(function() {
    return self.PossessionChanges()
      .filter(function(item) {
        return item.SelectedFrom() != undefined;
      })
      .map(function(item) {
        return item.SelectedFrom();
      });
  });

  self.setOptionDisable = function(option, item) {
    if (item)
      ko.applyBindingsToNode(option, {
        disable: item.disabled
      }, item);
  }

  self.AvailableFrom = ko.computed(function() {
    var available = self.AllFromList.slice();
    for (var i = 0; i < available.length; i++) {
      available[i].disabled = available[i].disabled || ko.observable(false);
      available[i].disabled((self.UsedFrom().indexOf(available[i].ID) >= 0));
    }
    return available;
  });

  self.AvailableTo = ko.computed(function() {
    var available = self.AllToList.slice();
    for (var i = 0; i < available.length; i++) {
      available[i].disabled = available[i].disabled || ko.observable(false);
      available[i].disabled((self.UsedTo().indexOf(available[i].ID) >= 0));
    }
    return available;
  });

  self.addPossessionChange = function() {
    self.PossessionChanges.push(new PossessionChangeVM(self.PossessionChanges().length + 1));
  }

  self.removePossessionChangeChange = function(possessionChange) {
    self.PossessionChanges.remove(possessionChange);
  }
}

function PossessionChangeVM(possessionChangeId) {
  var self = this;

  self.possessionChangeId = ko.observable(possessionChangeId);
  self.SelectedFrom = ko.observable();
  self.SelectedTo = ko.observable();

  self.ChangeType = ko.pureComputed(function() {
    if (self.SelectedFrom() !== undefined && self.SelectedTo() !== undefined) {
      return 'Update';
    } else if (self.SelectedFrom() === undefined && self.SelectedTo() === undefined) {
      return '';
    } else if (self.SelectedFrom() === undefined) {
      return 'Add';
    } else if (self.SelectedTo() === undefined) {
      return 'Remove';
    } else {
      return '';
    }
  });
}

function SelectedPerson(isAdult, name, id) {
  var self = this;

  self.IsAdult = ko.observable(isAdult);
  self.Name = ko.observable(name);
  self.ID = ko.observable(id);
}

ko.applyBindings(new BookPossessionTransferVM());
#tblPossessionChanges {
  width: 70%;
  height: 100px;
  text-align: center;
  table-layout: fixed;
}

#tblPossessionChanges td,
#tblPossessionChanges th {
  padding: 1rem;
}

#tblPossessionChanges thead th {
  text-align: center;
}

#tblPossessionChanges thead th:first-child {
  text-align: left;
  width: 10%;
}

#tblPossessionChanges tbody td:first-child {
  text-align: left;
  width: 10%;
}

#tblPossessionChanges>tbody>tr>td.prompt>a {
  font-weight: bold;
}

#tblPossessionChanges tbody td select {
  width: 75%
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.12/js/select2.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />

<div>
  <table id="tblPossessionChanges">
    <thead>
      <tr>
        <th><a href="#" class="buttonSmall" data-bind="click: addPossessionChange">Add</a></th>
        <th>From</th>
        <th>To</th>
      </tr>
    </thead>
    <tbody data-bind="foreach: PossessionChanges">
      <tr>
        <td class="prompt">
          <a href="#" class="buttonSmall" data-bind="click: $root.removePossessionChange">Delete</a> </td>
        <td>
          <select class="form-control" 
                  data-bind="options: $root.AvailableFrom, 
                             value: SelectedFrom,
                             optionsText: function(i) {return i.Name}, 
                             optionsValue: function(i) {return i.ID},
                             optionsCaption: 'Please select a Person...',
                             optionsAfterRender: $root.setOptionDisable,
                             select2: { placeholder: 'Please select a Person...', allowClear: false}">          
          </select>
        </td>
        <td>
          <select class="form-control"
                  data-bind="options: $root.AvailableTo, 
                             value: SelectedTo, 
                             optionsText: function(i) {return i.Name}, 
                             optionsValue: function(i) {return i.ID},
                             optionsCaption: 'Please select a Person...',
                             optionsAfterRender: $root.setOptionDisable,
                             select2: { placeholder: 'Please select a Person...', allowClear: false}">            
          </select>
        </td>
        <td>
          <span id="changeTypeSpan" data-bind="text: ChangeType"></span>
        </td>
      </tr>
    </tbody>
  </table>
  <br/>

</div>
...