Обновление коллекции бритв через нокаут - PullRequest
0 голосов
/ 29 апреля 2018

У меня есть этот интерфейс

enter image description here

И моя цель - обновить таблицу после нажатия Обновить кнопку на основе Id и Описание параметры

У меня следующий код

Html

<table class="table table-bordered table-striped table-hover">
    <thead>
        <tr>
            <th>Id</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model.Products)
        {
            <tr>
                <td>@item.Id</td>
                <td>@item.Description</td>
            </tr>
        }
    </tbody>
</table>

<label>Id</label>
<input data-bind="value: productId" type="text" class="form-control" />

<br />

<label>Description</label>
<input data-bind="value: productDescription" type="text" class="form-control" />

<br />

<button class="btn btn-primary" data-bind="click: update">Update</button>

JavaScript

<script type='text/javascript'>

            // Plain javascript alternative to jQuery.ready.
            (function () {

                // Convert server model to json object.
                var json = {"products":[{"id":1,"description":"Product A"},{"id":2,"description":"Product B"},{"id":3,"description":"Product C"}],"categoryName":"chocolates"};

                function viewModel()
                {
                    var index;

                    // Store default this to self, to be able use self in subfunctions.
                    var self = this;

                    // Product array from server.
                    self.products = json.products;

                    // Automatic refreshed parameter in UI.
                    self.categoryName = ko.observable(json.categoryName);

                    // Update form parameters.
                    self.productId = null;
                    self.productDescription = null;

                    // Update function.
                    self.update = function () {

                        // Get products collection index.
                        index = self.products.findIndex(function (product) {
                            return product.Id == self.productId
                        });

                        // Throws -1, index was not found !
                        alert(index);

                        // Assign new value.
                        // self.products[index].description(self.productDescription);
                    };
                }

                // Apply viewModel to UI
                ko.applyBindings(new viewModel());

            })();

    </script>

Мне нужна помощь с двумя вещами

  1. Обновление нокаута viewmodel (коллекция self.products на основе входных данных Id и Description в функции viewModel.Update)
  2. Обновить таблицу (я не знаю, как связать строки при использовании бритвы foreach)

EDIT:

Когда я меняю петлю бритвы с помощью нокаута foreach

<tbody data-bind="foreach: products">
        <tr>
            <td data-bind="text: id"></td>
            <td data-bind="text: description"></td>
        </tr>
    </tbody>

тоже не работает: / Я попробовал некоторые изменения с наблюдаемыми

 <script type='text/javascript'>

            // Plain javascript alternative to jQuery.ready.
            (function () {

                // Convert server model to json object.
                var json = {"products":[{"id":1,"description":"Product A"},{"id":2,"description":"Product B"},{"id":3,"description":"Product C"}],"categoryName":"chocolates"};

                function viewModel()
                {
                    var index;

                    // Store default this to self, to be able use self in subfunctions.
                    var self = this;

                    // Product array from server.
                    self.products = ko.observable(json.products);

                    // Automatic refreshed parameter in UI.
                    self.categoryName = ko.observable(json.categoryName);

                    // Update form parameters.
                    self.productId = ko.observable();
                    self.productDescription = ko.observable();

                    // Update function.
                    self.update = function () {

                        self.products()[self.productId()-1].description = self.productDescription()    
                    };
                }

                // Apply viewModel to UI
                ko.applyBindings(new viewModel());

            })();

    </script>

Я не получаю сообщение об ошибке, но значение в html-таблице не изменяется.

1 Ответ

0 голосов
/ 25 июня 2018

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

Следующий код будет обновляться только при изменении всей ссылки на объект. IE, если вы заполняете self.products новым объектом. Он не будет обновляться, если вы измените свойство существующего объекта.

// Product array from server.
self.products = ko.observable(json.products);

Вам потребуется изменить код, чтобы индивидуально применять наблюдаемые свойства к вашему объекту json, когда он поступает с сервера.

// Product array from server.
self.products = ko.observableArray([]); //Changed to array type
for(var i = 0; i < json.products.length; i++){
    self.products.push({
        id: json.products[i].id,
        description: ko.observable(json.products[i].description)
    });
}

И затем вам нужно будет обновить значение с помощью функции getter / setter.

// Update function.
self.update = function () {
    self.products()[Number(self.productId())-1].description(self.productDescription());
};

  // Convert server model to json object.
  var json = {"products":[{"id":1,"description":"Product A"},{"id":2,"description":"Product B"},{"id":3,"description":"Product C"}],"categoryName":"chocolates"};

  function viewModel()
  {
    var index;

    // Store default this to self, to be able use self in subfunctions.
    var self = this;

    // Product array from server.
    self.products = ko.observableArray([]); //Changed to array type
    for(var i = 0; i < json.products.length; i++){
        self.products.push({
            id: json.products[i].id,
            description: ko.observable(json.products[i].description)
        });
    }

    // Automatic refreshed parameter in UI.
    self.categoryName = ko.observable(json.categoryName);

    // Update form parameters.
    self.productId = ko.observable();
    self.productDescription = ko.observable();

    // Update function.
    // Update function.
    self.update = function () {
        self.products()[Number(self.productId())-1].description(self.productDescription());
    };
    
  }

  // Apply viewModel to UI
  ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<table class="table table-bordered table-striped table-hover">
    <thead>
        <tr>
            <th>Id</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: products">
        <tr>
            <td data-bind="text: id"></td>
            <td data-bind="text: description"></td>
        </tr>
    </tbody>
</table>
<br/>

<label>Id: </label>
<input data-bind="value: productId" type="text" class="form-control" />

<br />

<label>Description: </label>
<input data-bind="value: productDescription" type="text" class="form-control" />

<br />

<button class="btn btn-primary" data-bind="click: update">Update</button>
...