Knockout - Как я могу преобразовать динамически заполненный флажок в переключатель (да / нет)? - PullRequest
0 голосов
/ 05 мая 2018

У меня есть флажок, который динамически заполняет массив объектов, но теперь мне нужно преобразовать его в переключатели, чтобы теперь пользователь мог выбрать либо Да, либо Нет (вместо одного флажка)

<!--
From (checkboxes):
   [] Customer 1
   [] Customer 2

To (radio button Yes/No options):

  Customer 1 (customer code)
  [] Yes
  [] No
-->

У меня есть флажок моего рабочего флажка и попытки (пока не удачные) преобразовать их в переключатели - fiddle

Согласно скрипте, в конечном итоге мне нужно отправить обратно массив выбранных клиентов {cusotmerType, checkedvalue}

Любой совет приветствуется, чтобы помочь мне направиться в правильном направлении. Большое спасибо

function Customer(type,checked)
{
  var self = this;
  
  self.CustomerType = ko.observable(type); 
  self.IsChecked = ko.observable(checked || false);
}

function VM()
{
  var self = this;
  
  //dynamically populated - this is for testing puposes
  self.AllCustomers = ko.observableArray([
    { 
      code: "001",
      name:'Customer 1'
    },
    { 
      code: "002",
      name:'Customer 2'
    },
    { 
      code: "003",
      name:'Customer 3'
    },
  ]);
  
 self.selectedCustomers = ko.observableArray([]);
 self.Customer = ko.observableArray([]); //I need to POST this back- all selected customers
  
//return all customers that checked the box
self.selectedCustomers.subscribe(function() {
self.Customer.removeAll();
  ko.utils.arrayForEach(self.selectedCustomers(), function(item) {
      self.Customer.push(new Customer(item, true));
  });
});

}
ko.applyBindings(new VM());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<!-- ko foreach: AllCustomers -->
  <input type="checkbox" data-bind="value: $data.code, checked:$parent.selectedCustomers" /> 
   
  <span data-bind="text: $data.name"></span>
  <!-- /ko -->
  
  <h4>Selected customers</h4> 
  <div data-bind="foreach: Customer">
    <span data-bind="text: CustomerType"></span>
    <span data-bind="text: IsChecked"></span>
    <span>,</span>
  </div> 
  <br>
  <!-- I need to convert them into radio options 
  eg:
  Customer 1 (can be customer code)
  [] Yes
  [] No
  -->
  <strong>
  Not working yet..only one of the Yes/No can be selected among all cusotmers
  </strong><br><br>
   <!-- ko foreach: AllCustomers -->
   <span data-bind="text: $data.name"></span><br>
   <input type="radio" data-bind="value: $data.code,checked:$parent.selectedCustomers" />Yes
   <input type="radio" value="No" data-bind="checked:$parent.selectedCustomers" />No
   <br>
  <!-- /ko -->

1 Ответ

0 голосов
/ 07 мая 2018

С вашим кодом довольно много проблем, и наиболее важными из них являются:

  • радиокнопки работают в группах, которые можно указать с помощью атрибута name
  • нокаут действительно не работает с observableArray (selectedCustomers в вашем случае) для радиокнопок и флажков.

Я обновил вашу скрипку https://jsfiddle.net/w75px6r2/7/ Я действительно не знал, что я могу изменить, а что нет. Поэтому я оставил входной и выходной массив одинаковыми. Я только изменил обработку данных между ними. Исходя из этого, вам нужно найти лучшее решение.

В первой части я только добавил еще один массив, подготовленный для просмотра, который просто расширяет ваши оригинальные элементы на isSelected observable.

Тогда я просто связываю это в представлении. Теперь вы должны увидеть, что флажки и радиокнопки должны работать в одном и том же виде.

function Customer(type, name, checked) {
  var self = this;

  self.CustomerType = ko.observable(type);
  self.Name = ko.observable(name);
  self.IsChecked = ko.observable(checked || false);
}

function VM() {
  var self = this;

  //dynamically populated - this is for testing purpose
  self.AllCustomers = ko.observableArray([{
      code: "001",
      name: 'Customer 1'
    },
    {
      code: "002",
      name: 'Customer 2'
    },
    {
      code: "003",
      name: 'Customer 3'
    },
  ]);

  self.AllCustomersViewModel = ko.observableArray(
    self.AllCustomers().map(function(value) {
      value.isSelected = ko.observable(false);
      return value;
    }));

  self.selectedCustomers = ko.pureComputed(function() {
    var result = [];
    ko.utils.arrayForEach(self.AllCustomersViewModel(), function(item) {
      if (item.isSelected()) {
        result.push(item);
      }
    });
    return result;
  });
  self.Customer = ko.observableArray([]); //I need to POST this back- all selected customers

  //return all customers that checked the box
  self.selectedCustomers.subscribe(function() {
    self.Customer.removeAll();
    ko.utils.arrayForEach(self.selectedCustomers(), function(item) {
      self.Customer.push(new Customer(item.code, item.name, true));
    });
  });

}
ko.applyBindings(new VM());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<!-- ko foreach: AllCustomersViewModel -->
<input type="checkbox" data-bind="checked: isSelected" />

<span data-bind="text: name"></span>
<!-- /ko -->

<h4>Selected customers</h4>
<div data-bind="foreach: Customer">
  <span data-bind="text: CustomerType"></span>
  <span data-bind="text: IsChecked"></span>
  <span>,</span>
</div>
<br>

<!-- I need to convert them into radio options 
  eg:
  Customer 1
  [] Yes
  [] No
  -->
<strong>
  Not working yet..only one of the Yes/No can be selected among all customers
  </strong><br><br>
<!-- ko foreach: AllCustomersViewModel -->
<span data-bind="text: name"></span><br>
<input type="radio" data-bind="value: true, checked: isSelected, attr: {name: $index}" />Yes
<input type="radio" data-bind="value: false, checked: isSelected, attr: {name: $index}" />No
<br>
<!-- /ko -->
...