【问题标题】:Update razor collection via knockout通过淘汰赛更新剃须刀收藏
【发布时间】:2018-10-09 15:19:17
【问题描述】:

我有这个用户界面

我的目标是在点击更新按钮后根据IdDescription参数更新table p>

我有以下代码

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. 更新淘汰视图模型(self.products 集合基于 viewModel.Update 函数中的 Id 和 Description 输入)
  2. 更新表(我不知道如何绑定行,使用 razor foreach 时)

编辑:

当我使用 Knockout foreach 更改 Razor 循环时

<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 表中的值没有改变。

【问题讨论】:

  • 剃须刀循环仅存在于服务器上,因此要更新它,您需要将表单提交回服务器重新渲染,或者您应该用敲除循环替换剃刀循环前端。
  • 我不能同时拥有两个,用剃刀渲染淘汰赛属性吗?我可以在服务器上呈现与客户端相同的 html。无论如何,如果我将使用淘汰赛循环,如何在点击事件之后而不是立即更新集合中的项目(因为必须首先验证和存储输入)?
  • 您可以使用 razor sure 添加淘汰赛绑定,但问题在于上下文。如果您没有淘汰赛循环淘汰赛不知道您在哪一行,也不知道将这些绑定应用于什么。每个绑定都将尝试绑定到根视图模型。现在您可以添加一堆其他数据属性来为每一行提供一个索引,并使用一些 jquery 来查找具有匹配属性的行并手动更新它,但是您最好不要使用敲除。
  • 看起来在您之前的问题 [stackoverflow.com/questions/50081008/… 您有一个最终正常工作的淘汰赛循环。你为什么决定用剃须刀循环代替它?
  • 我只是好奇,如果我没有遗漏什么。 Razor 有一些我想与淘汰赛一起使用的优点,但如果它不兼容,我只能使用淘汰赛。

标签: asp.net-mvc razor knockout.js


【解决方案1】:

您的淘汰代码看起来基本正确,但您的 UI 没有更新,因为您正在更改的值是不可观察的。如果您希望对项目的更改反映在表中,您需要使每个字段都更新一个 observable,而不是为整个 json 对象设置一个 observable 属性。

以下代码仅在整个对象引用更改时才会更新。 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>

【讨论】:

    猜你喜欢
    • 2013-10-18
    • 2016-12-05
    • 2013-03-04
    • 1970-01-01
    • 2014-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多