Pushing Values Into nested ko.observableArray

十年热恋 提交于 2019-12-12 00:33:59

问题


I want to nest a list of vendors into an existing JSON Payload that I get from the server, based on if the item within the JSON Payload requires a vendor.

What I want to end up with is something that looks like this:

    {
        "ProductName": "Product123",
        "RequiredComponents": "CAP 10% H/Vol",
        "StockCode": "142111411",
        "RequiredQtyByBom": 4,
        "QtyUnassignedInWarehouse": 0,
        "QtyAllocatedInWarehouse": 40,
        "PCBReference": "442C",
        "QtyOnOrder": 26,
        "Vendors": [],
        "RequireVendor": false
    },
    {
        "ProductName": "Product123",
        "RequiredComponents": "Screws",
        "StockCode": "Screws",
        "RequiredQtyByBom": 1,
        "QtyUnassignedInWarehouse": 0,
        "QtyAllocatedInWarehouse": 14,
        "PCBReference": "Screws",
        "QtyOnOrder": 26,
        "Vendors": [
                      {"VendorID": "3", 
                      "VendorName": "ABC Supplier",
                      "VendorMOQ": 50000,
                      "VendorItemPrice": 322},
                      {"VendorID": "4", 
                      "VendorName": "DEF Supplier",
                      "VendorMOQ": 4,
                      "VendorItemPrice": 120}
                   ],
        "RequireVendor": true
    },
    {
        "ProductName": "Product123",
        "RequiredComponents": "14141415",
        "StockCode": "151555231",
        "RequiredQtyByBom": 1,
        "QtyUnassignedInWarehouse": 0,
        "QtyAllocatedInWarehouse": 170,
        "PCBReference": "1414",
        "QtyOnOrder": 26,
        "Vendors": [],
        "RequireVendor": false
    }

I was thinking of doing this with 2 AJAX call an push the values into the Observable array.

AJAX Call 1: Create The Initial Payload fro Products

 MyDataViewModel.SelectedOrderID.subscribe = ko.computed(function () {
        $.ajax({
            url: "/URLToMethod/GetBomStockByProductID",
            data: { OrderID: ko.toJS(MyDataViewModel.SelectedOrderID) },
            type: "GET",
            contentType: "application/json; charset=utf-8",
            dataType: "JSON",
            timeout: 10000,
            success: function (Result) {
                for (var i = 0; i < Result.d.length; i++) {
                    element = Result.d[i];
                    MyDataViewModel.CheckStock.push({
                        ProductName: element.ProductName, RequiredComponents: element.RequiredComponents, StockCode: element.StockCode, RequiredQtyByBom: element.RequiredQtyByBom, QtyUnassignedInWarehouse: element.QtyUnassignedInWarehouse, QtyAllocatedInWarehouse: element.QtyAllocatedInWarehouse, PCBReference: element.PCBReference, QtyOnOrder: element.QtyOnOrder, Vendors: ko.observableArray(), RequireVendor: ko.computed(function () {
                            if ((element.RequiredQtyByBom * element.QtyOnOrder) > element.QtyAllocatedInWarehouse) {
                                return true
                            } else {
                                return false
                            }
                        })
                    }
                    );
                }
            },
            error: function (xhr, status) {
                alert(status + " - " + xhr.responseText);
            }
        });
    });

AJAX Call 2: Push Values into Vendors ko.observableArray() Created in First payload

 MyDataViewModel.PurchaseReqHasVendorDetails = ko.computed(function () {
        var self = MyDataViewModel;
        for (var i = 0; i < self.CheckStock().length; i++) {
            if (self.CheckStock()[i].RequirePO()) {
                $.ajax({
                    url: "/URLToMethod/GetVendorsByProductName",
                    data: { ProductName: self.CheckStock()[i].ProductName },
                    type: "GET",
                    contentType: "application/json; charset=utf-8",
                    dataType: "JSON",
                    timeout: 10000,
                    success: function (Result) {
                        for (var i = 0; i < Result.d.length; i++) {
                            element = Result.d[i];
                            self.CheckStock()[i].Vendors.push({ VendorID: element.VendorID, VendorName: element.VendorName, VendorMOQ: element.VendorMOQ, VendorPrice: element.VendorPrice });
                        }
                    },
                    error: function (xhr, status) {
                        alert(status + " - " + xhr.responseText);
                    }
                });
                return true;
            } else {
                return false;
            }
        }
    });

But this doesn't work. It creates the initial payload but it does not obtain the second payload and push it into the observableArray that I created.

Any Advice would be greatly appreciated


回答1:


You can use the mapping plugin to do this easily. Suppose you retrieve a slightly different JS from the server (or modify it a bit after you receive it), like this:

var data = {
    [ /* Your example data with products and nested vendors here */ ]
}

Creating the view models can be as simple as:

var viewModel = ko.mapping.fromJS(data);
ko.applyBindings(viewModel);

If you don't want auto-generated view models but use your own ViewModel constructor functions you can use the mapping plugin to add additional "mapping options". The documentation has great examples on that.

Here's a fiddle with a demo that includes your data.



来源:https://stackoverflow.com/questions/18502540/pushing-values-into-nested-ko-observablearray

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!