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

Не уверен, что я правильно формулирую это.

У меня есть observableArray, и я могу добавить в этот массив входные данные, а также удалить элемент списка. но если я изменю созданный элемент, я потеряю соединение с массивом. Как я могу сохранить привязку к массиву?

Скрипка прикреплена

HTML

<div class = "group-settings-container mt-4">
<div class = "row">
<div class = "col-md-3">
  <h4><i class = "fas fa-object-group"></i> Create Groups</h4>
</div>

<div class = "col-md-6">
  <div class = "input-group">
    <input type = "text" class = "form-control create-group-name" data-bind = "value: groupItemToAdd, valueUpdate: 'afterkeydown' " placeholder = "Enter group name" value = "">
    <div class = "input-group-append">
      <button class = "btn btn-primary add-group-btn" data-bind = "click: addGroupItem, enable: groupItemToAdd().length > 0" type = "button"><i class = "fas fa-plus"></i>
                      Add group</button>
    </div>
  </div>
</div>


<div class = "create-groups-container mb-4">
  <ul class = "list-group create-group-list my-2" data-bind = "foreach: allGroupItems">
    <li class = "list-group-item">
      <div class = "input-group">
        <input type = "text" class = "form-control created-group-input" data-bind = "value: $data">
        <div>
          <button class = "btn btn-danger remove-group-item-btn" data-bind = "click: $parent.removeSelectedGroupItem" type = "button"><i class = "fas fa-times"></i>
                        Remove</button>
        </div>
      </div>
    </li>
  </ul>
</div>
<!-- end create groups container  -->

</div>
<!-- end group settings container -->

JS

 function ViewModel() {
 var self = this;
 self.groupItemToAdd = ko.observable("");
 self.allGroupItems = ko.observableArray([]);


 self.addGroupItem = function() {
 if ((self.groupItemToAdd() != "") &&     (self.allGroupItems.indexOf(self.groupItemToAdd()) < 0)) {
  self.allGroupItems.push(self.groupItemToAdd());
  }
  self.groupItemToAdd(""); // clear the input
 }

 self.removeSelectedGroupItem = function(index) {
 // self.allGroupItems.splice(index, 1);
// console.info(self.allGroupItems.splice(index, 1));
self.allGroupItems.remove(index);
}
}
// end ViewModel

ko.applyBindings(new ViewModel());

Если ответ решил вашу проблему, отметьте его как принятый. См.: Что мне делать, когда кто-то отвечает на мой вопрос?

adiga 19.03.2019 18:06
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
55
1

Ответы 1

У вас есть observableArray. Это означает, что любые изменения в массиве отслеживаются и обновляются. Элементы внутри него — просто строки. Они не observables. Любые изменения, которые вы делаете из пользовательского интерфейса, не обновляются обратно в модель представления. Это поведение не ограничивается строками. То же самое применимо, если у вас есть observableArray обычных литералов объектов javascript.

Из документация:

Simply putting an object into an observableArray doesn’t make all of that object’s properties themselves observable. Of course, you can make those properties observable if you wish, but that’s an independent choice. An observableArray just tracks which objects it holds, and notifies listeners when objects are added or removed.

Таким образом, вместо добавления строк в observableArray вы можете поместить объект со свойством observable в observableArray. Теперь изменения свойства item отслеживаются. Важно сделать свойство observable, иначе вы столкнетесь с той же проблемой.

function ViewModel() {
  var self = this;
  self.groupItemToAdd = ko.observable("");
  self.allGroupItems = ko.observableArray([]);

  self.addGroupItem = function() {
    if (self.groupItemToAdd() && !self.allGroupItems().some(a => a.item() === self.groupItemToAdd())) {
      self.allGroupItems.push({
        item: ko.observable(self.groupItemToAdd())
      });
    }
    self.groupItemToAdd(""); // clear the input
  }

  self.removeSelectedGroupItem = function(index) {
    self.allGroupItems.remove(index);
  }
}

ko.applyBindings(new ViewModel());
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src = "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
<link href = "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel = "stylesheet" />

<div class = "group-settings-container mt-4">
  <div class = "row">
    <div class = "col-md-3">
      <h4><i class = "fas fa-object-group"></i> Create Groups</h4>
    </div>

    <div class = "col-md-6">
      <div class = "input-group">
        <input type = "text" class = "form-control" data-bind = "value: groupItemToAdd, valueUpdate: 'afterkeydown' " placeholder = "Enter group name">
        <div class = "input-group-append">
          <button class = "btn btn-primary add-group-btn" data-bind = "click: addGroupItem, enable: groupItemToAdd().length > 0" type = "button">Add group</button>
        </div>
      </div>
    </div>

      <ul class = "list-group create-group-list my-2" data-bind = "foreach: allGroupItems">
        <li class = "list-group-item">
          <div class = "input-group">
            <input type = "text" class = "form-control created-group-input" data-bind = "value: item">
            <div>
              <button class = "btn btn-danger remove-group-item-btn" data-bind = "click: $parent.removeSelectedGroupItem" type = "button">Remove</button>
            </div>
          </div>
        </li>
      </ul>
  </div>

  <span data-bind = "text: allGroupItems().map(a => a.item())"></span>

Примечание:

  • Вам нужно изменить входную привязку внутри foreach с $data на item (имя наблюдаемого свойства)

  • Чтобы проверить, добавлен ли элемент группы, используйте some следующим образом: self.allGroupItems().some(a => a.item() === self.groupItemToAdd())

  • Последний span демонстрирует, что наблюдаемая обновляется

Другие вопросы по теме