Двухсторонняя привязка данных не работает с нокаутом ObservableArrays - PullRequest
0 голосов
/ 30 августа 2018

У меня следующий код, который имеет две функции.

  1. При нажатии кнопки «Добавить еще» добавьте новое значение в наблюдаемый массив, добавьте новое текстовое поле в пользовательский интерфейс
  2. При нажатии кнопки Сохранить отображаются значения в текстовом поле на делении.

var model = function() {
  var self = this;
  self.inventoryItems = ko.observableArray();

  myArray = ["Value1", "V1lue2", "Value3", "Value4"];
  self.inventoryItems(myArray);

  self.addItems = function(vm) {
    self.inventoryItems.push('New Item');
  }

  self.SaveInventory = function(data) {
    $('#htmlBlock').html(myArray);
    console.log(myArray)
  };

};

ko.applyBindings(new model());
ul {
  list-style: none;
}

li {
  margin-top: 5px;
}

.info-text,
a,
button {
  margin-top: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<ul data-bind="foreach: inventoryItems">
  <li>
    <input data-bind="value: $data" />
  </li>
</ul>
<div>
  <a data-bind="click: addItems">+ Add more</a>
</div>
<button type="submit" class="btn btn-accent" data-bind="click: SaveInventory">Save changes</button>
<div class='info-text' id="htmlBlock">
</div>

С этим кодом мой пользовательский интерфейс хорошо инициализируется, и когда я нажимаю «Добавить еще», можно получить новое текстовое поле и myArray / inventoryItems также работает нормально.

Но если я отредактирую какой-либо элемент и сохраню значение, я не верну значение обновления.

Чего мне не хватает?

1 Ответ

0 голосов
/ 30 августа 2018

Нет необходимости в отдельной ссылке на базовый массив в наблюдаемом массиве, он только сбивает с толку. Считайте значение, используя self.inventoryItems().

Хороший способ увидеть, как ваша модель в реальном времени выглядит, - использовать элемент с data-bind="text: ko.toJSON($data, null, '\t')"

Чтобы иметь двухстороннюю привязку, вам нужно сделать каждое значение (для полей ввода) наблюдаемым. Обычно я бы использовал для этого отдельный конструктор.

function EditableField(initialValue) {
  // each value you want to be able to have a two-way binding for needs to be observable
  this.value = ko.observable(initialValue);
}

var model = function() {
  var self = this;
  self.inventoryItems = ko.observableArray(["Value1", "V1lue2", "Value3", "Value4"].map(function(item) {
    // run each array value through constructor
    return new EditableField(item);
  }));

  self.addItems = function(vm) {
    self.inventoryItems.push(new EditableField('New Item'));
  }

  self.SaveInventory = function(data) {
    console.log(ko.toJS(self.inventoryItems)); // fetch the updated array
  };

};

ko.applyBindings(new model());
ul {
  list-style: none;
}
li {
  margin-top: 5px;
}
.info-text,
a,
button {
  margin-top: 20px;
}




  
    <!-- use textInput binding for live updates, bound to the value property from constructor -->
    
  


  + Add more
<!-- display the model in real time -->

...