Knockout observableArray не обновляет все свойства проверенного значения

Я использую Knockout для заполнения observableArray на основе проверенных значений отдельного observableArray. Я могу заставить $data скопировать во второй набор, но проходит только одно свойство. Я хотел бы иметь весь объект доступным. Это проблема с отображением или что-то с привязками?

HTML:

    <form role="form" data-bind="foreach: Colors">
      <input type="checkbox" data-bind="checkedValue: name, click: $root.ToggleAssociation, checked: $root.ColorChoice">
      <label data-bind="attr: {'for' : name}, text: id() + ' ' + name()"></label>
    </form>
    <div data-bind="foreach: ColorChoice">
      <span data-bind="text: $rawData.Id, style: { 'background-color': $rawData.Name }"></span>
    </div>

JavaScript:

    function Color(data) {
      var self = this;

      self.id = ko.observable(data.id);
      self.name = ko.observable(data.name);
      self.selected = ko.observable(false);
    }

    function viewModel() {

      var self = this;

      self.Colors = ko.observableArray([]);
      self.ColorChoice = ko.observableArray();

      self.Id = ko.observable();
      self.Color = ko.observable();

      self.init = function () {
        self.Colors.push(new Color({ id: 1, name: 'Red' }));
        self.Colors.push(new Color({ id: 2, name: 'Orange' }));
        self.Colors.push(new Color({ id: 3, name: 'Yellow' }));
        self.Colors.push(new Color({ id: 4, name: 'Green' }));
        self.Colors.push(new Color({ id: 5, name: 'Blue' }));
        self.Colors.push(new Color({ id: 6, name: 'Purple' }));
      }

      self.ToggleAssociation = function (item) {
        if (item.selected() === true)
          console.log("dissociate item " + item.id());
        else
          console.log("associate item " + item.id() + " " + item.name());
        self.Id(item.id());
        self.Color(item.name());
        item.selected(!(item.selected()));
        return true;
      };
    };

    var vm = new viewModel();
    ko.applyBindings(vm);
    vm.init();

https://jsfiddle.net/Razzle/ff1945ye/


person Razzle    schedule 26.08.2016    source источник


Ответы (2)


У вас есть доступ ко всем вашим переменным в вашей модели. Если я точно понимаю, что вы пытаетесь сделать, и вы хотите привязать событие click всякий раз, когда установлен флажок, вам нужно сделать что-то вроде этого.

Пример: https://jsfiddle.net/kyr6w2x3/77/

HTML:

<form role="form" data-bind="foreach: Colors">
  <input type="checkbox" data-bind="checkedValue: name, click: $root.ToggleAssociation ,checked:selected">
  <label data-bind="attr: {'for' : name}, text: id() + ' ' + name()"></label>
</form>
<div data-bind="foreach: ColorChoice">
  <span data-bind="text: name, style: { 'background-color':name }" class="colors"></span>
</div>

JS:

 function Color(data) {
  var self = this;

  self.id = ko.observable(data.id);
  self.name = ko.observable(data.name);
  self.selected = ko.observable(false);
}

function viewModel() {

  var self = this;

  self.Colors = ko.observableArray([]);
  self.ColorChoice = ko.observableArray();

  self.Id = ko.observable();
  self.Color = ko.observable();

  self.init = function () {
    self.Colors.push(new Color({ id: 1, name: 'Red' }));
    self.Colors.push(new Color({ id: 2, name: 'Orange' }));
    self.Colors.push(new Color({ id: 3, name: 'Yellow' }));
    self.Colors.push(new Color({ id: 4, name: 'Green' }));
    self.Colors.push(new Color({ id: 5, name: 'Blue' }));
    self.Colors.push(new Color({ id: 6, name: 'Purple' }));
  }

  self.ToggleAssociation = function (item) {
   // here you can go through your array and do whatever you want to do
    item.selected(!item.selected());
     ko.utils.arrayFirst(self.Colors(), function (color) {
      if(color.id() == item.id()){
       if (item.selected()){self.ColorChoice.push(color);
       }else{self.ColorChoice.remove(color);
       }
      }
     });
    return true;
  };
};

var vm = new viewModel();
ko.applyBindings(vm);
vm.init();
person Matin Kajabadi    schedule 26.08.2016
comment
Красиво-спасибо! Итак, ko.utils.arrayFirst проверяет вторичный массив, чтобы увидеть, совпадает ли элемент? - person Razzle; 26.08.2016
comment
ko.utils.arrayFirst выполняет функцию для каждого элемента в массиве и возвращает первый элемент, где функция оценивается как true. Мы перебираем основной массив, и все, что соответствует выбранному элементу, мы помещаем во второй массив, и если он не выбран, мы удаляем его. - person Matin Kajabadi; 26.08.2016
comment
Понятно! Спасибо еще раз. - person Razzle; 26.08.2016
comment
Обновил вашу скрипку с помощью «return: true» в строке 37, так как она не устанавливала фактическую галочку. jsfiddle.net/kyr6w2x3/77 - person Razzle; 07.09.2016

вы можете сделать это намного проще, как показано ниже

function Color(data) {
    var self = this;
    self.id = ko.observable(data.id);
    self.name = ko.observable(data.name);
    self.selected = ko.observable(false);
}

function viewModel() {
    var self = this;
    self.Colors = ko.observableArray([]);
    self.ColorChoice = ko.observableArray([]);
    self.init = function() {
        self.Colors.push(new Color({ id: 1, name: 'Red' }));
        self.Colors.push(new Color({ id: 2, name: 'Orange' }));
        self.Colors.push(new Color({ id: 3, name: 'Yellow' }));
        self.Colors.push(new Color({ id: 4, name: 'Green' }));
        self.Colors.push(new Color({ id: 5, name: 'Blue' }));
        self.Colors.push(new Color({ id: 6, name: 'Purple' }));
    }
};

var vm = new viewModel();
ko.applyBindings(vm);
vm.init();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<form role="form" data-bind="foreach: Colors">
    <label>
        <input type="checkbox" data-bind="value: $data, checked:$root.ColorChoice">
        <span data-bind="text: id() + ' ' + name()"></span>
    </label>
</form>
<div data-bind="foreach: ColorChoice">
    <span data-bind="text: id() + ' ' + name(), style: { 'background-color':name }"></span>
</div>

person Ja9ad335h    schedule 26.08.2016
comment
Спасибо! Это простое решение, но мне нужно сохранить там событие клика. Тем не менее, было полезно увидеть урезанную версию. - person Razzle; 26.08.2016