Knockout.js选择数据绑定值未读取但写入

时间:2016-08-25 07:45:25

标签: javascript knockout.js

这是我的HTML代码:

<!-- ko foreach: warehouseOrders().StoreOrders -->
                    <tr>
                        <td>
                            <b data-bind="text: Product"></b>
                        </td>
                        <td>
                            <b data-bind="text: Store"></b>`enter code here`
                        </td>
                        <td>
                            <b data-bind="text: Quantity"></b>
                        </td>
                        <td>
                            <select data-bind=" value: OrderStatusId , options: $parent.orderStatuses(), optionsText: 'Status', optionsValue: 'Id'"></select>
                            <b data-bind="text: OrderStatusId"></b>
                        </td>
                    </tr>
                    <!--/ko-->

因此StoreOrders包含所有属性:Product,Store,Quantity,OrderStatusId。

具体问题:选择选项:$parent.orderStatuses()包含orderstatuses列表(Id,Status)。我为select设置了text和value属性。一切正常,当选择一个选项时,它被写入对象的OrderStatusId属性,但最初,OrderStatusId包含一个值,该值应在select中读取和设置。因此,当我打开时,select应该在该值上。

以下是模型:

主要课程:

public class WarehouseDTO
    {
        public System.Guid Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public List<StoreOrderDTO> StoreOrders { get; set; }
        public List<StoreWarehouseDTO> StoreWarehouses { get; set; }
        public List<WarehouseProductDTO> WarehouseProducts { get; set; }
    }

和StoreOrderDTO

public class StoreOrderDTO
    {
        public System.Guid Id { get; set; }
        public string Product { get; set; }
        public string Store { get; set; }
        public string Warehouse { get; set; }
        public int Quantity { get; set; }
        public System.Guid OrderStatusId { get; set; }
    }

使用Javascript:

self.warehouseOrdersRequest = function (item) {
        ajaxHelper('/api/OrderStatus', 'GET').done(function (data) {
            self.orderStatuses(data);
        });
        self.warehouseOrders(item);
    }

此处item表示WarehouseDTO类型的1个对象,OrderStatuses被赋予对象数组{Id,Status}

表的完整代码

<!--ko if : warehouseOrders()-->
    <div>
        <div class="col-md-4">
            <div class="panel panel-default">
                <div class="panel-heading">
                    <h2 class="panel-title"><b data-bind="text: warehouseOrders().Name"></b> - Orders</h2>
                </div>
                <table class="table">
                    <tr>
                        <th>
                            @Html.DisplayName("Product")
                        </th>
                        <th>
                            @Html.DisplayName("Store")
                        </th>
                        <th>
                            @Html.DisplayName("Quantity")
                        </th>
                        <th>
                            @Html.DisplayName("Order Status")
                        </th>
                    </tr>

                    <!-- ko foreach: warehouseOrders().StoreOrders -->
                    <tr>
                        <td>
                            <b data-bind="text: Product"></b>
                        </td>
                        <td>
                            <b data-bind="text: Store"></b>
                        </td>
                        <td>
                            <b data-bind="text: Quantity"></b>
                        </td>
                        <td>
                            <select data-bind=" value: OrderStatusId , options: $parent.orderStatuses(), optionsText: 'Status', optionsValue: 'Id'"></select>
                            <b data-bind="text: OrderStatusId"></b>
                        </td>
                    </tr>
                    <!--/ko-->
                </table> 
            </div>
            <a href="#" data-bind="click: closeWarehouseOrders" class="btn btn-defaul">Cancel</a>
            <a href="#" data-bind="click: saveWarehouseOrders" class="btn btn-defaul">Save</a>
        </div>
    </div>
    <!--/ko-->

我发现了一些东西,在我选择一个项目后,它被写入OrderStatusId,显示<b data-bind="text: OrderStatusId"></b>(它之前没有),是的,我确定它中有一个值。

1 个答案:

答案 0 :(得分:1)

因为orderStatuses被加载为异步,而当前状态不是,所以knockout无法在此处正确初始化<select>数据绑定:

<select data-bind=" value: OrderStatusId , options: $parent.orderStatuses(), optionsText: 'Status', optionsValue: 'Id'"></select>

在绑定时,$parent.orderStatuses()是一个空数组。 OrderStatusId是一个字符串。没有选项可以查找用于设置初始值的option.Id == value

更新observable options数组时,knockout 显然不会重试将当前选定的值与其中一个新选项匹配。 (引用需要,我试图查找源代码来支持它,但是找不到它足够快......)

解决此问题的一种方法是在<select>尚未加载时阻止初始化statuses

<!-- ko if: orderStatuses().length -->
<select data-bind="options: orderStatuses"></select>
<!-- /ko -->

您可以在下面的示例中看到此修复程序。删除虚拟if绑定元素后,您将看到不再设置初始状态。此外,当您更换setItemsetStatuses的顺序时,您会发现不再需要额外的if-bind。

var vm = {
  item: ko.observable(),
  statuses: ko.observableArray([])
}

ko.applyBindings(vm);

var setItem = function() {

  vm.item({
    orders: ko.observableArray([{
        text: "Item 1",
        status: ko.observable(0)
      }, {
        text: "Item 2",
        status: ko.observable(1)
      }

    ])
  });
}

var setStatuses = function() {
  vm.statuses([{
    label: "Status 0",
    id: 0
  }, {
    label: "Status 1",
    id: 1
  }]);
}

setItem();
setStatuses();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<!-- ko if: item -->
<ul data-bind="foreach: item().orders">
  <li>
    <div data-bind="text: text"></div>
    
    <!-- ko if: $parent.statuses().length -->
    <select data-bind="options: $parent.statuses, value: status, optionsText: 'label', optionsValue: 'id'"></select>
    <strong data-bind="text: 'status: ' + status()"></strong>
    <!-- /ko -->
  </li>
</ul>
<!-- /ko -->