KnockoutJS - 使 NESTED JSON 字段可观察/可编辑

KnockoutJS - making NESTED JSON field observable / editable

我最近开始学习JS和KO,我完成了KO live教程并阅读了文档,但仍然有一些事情我自己想不通。只是想知道您是否可以帮助这个简单的应用程序,以便我可以进一步学习。

我有一个缩小为字符串的 json 对象,它只是一个包含食物项的数组,每个食物项也有部分数组。所以我的学习目标是显示每个食品名称,select 食品份量下拉列表和数量字段的输入字段(我想自己编辑这个值,所以需要观察)。我想不通的是,当我不断更改份量下拉列表 selection.

时,如何将数量值提取到输入字段中

我已经将我当前的代码上传到 jsfiddle 中以便于查看,我相信我已经非常接近让这个小应用程序正常工作了。

https://jsfiddle.net/2zkeycjb/

HTML 和JS代码:

<!DOCTYPE html>
<html>

<head>
    <title>KO</title>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
    <script type="text/javascript" src='https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.0/knockout-min.js'></script>
</head>

<body>

    <script type="text/javascript">
        var foodsJson = JSON.parse('[{"id":"ea17ca42-38d4-7e02-22ea-43b20fc7f3fc","name":"Macaroni","foodPortions":[{"id":"69869c2b-efbc-418f-98be-bb5651e595c5","quantity":1,"servingSize":"piece","calories":3},{"id":"0d7c01c9-4edd-4da5-91f6-fe18a14ff745","quantity":100,"servingSize":"g.","calories":157}]},{"id":"c6768773-4e0c-7255-4f0b-0205c7f78f42","name":"Salmon Maki","foodPortions":[{"id":"c9c6b7a9-83d0-4dc4-aebb-06948714da65","quantity":1,"servingSize":"cup","calories":305},{"id":"cf84c55f-8b91-4419-8868-275d8634f961","quantity":100,"servingSize":"g.","calories":184},{"id":"c8c4e813-6a50-4e8e-b5a2-4ae44e846b26","quantity":1,"servingSize":"oz (28.34 g.)","calories":52},{"id":"7fac51dd-2592-407e-a4da-6829a6536e6c","quantity":1,"servingSize":"piece","calories":28}]}]');

        function FoodPortion(foodPortion) {
            var self = this;

            self.portion = ko.observable(foodPortion);

            self.servingSize = ko.computed(function() {
                return self.portion().id;
            });

            self.servingSize = ko.computed(function() {
                return self.portion().servingSize;
            });

            self.quantity = ko.computed(function() {
                return self.portion().quantity;
            });

            self.calories = ko.computed(function() {
                return self.portion().calories;
            });
        }

        function Food(foodItem) {
            var self = this;

            self.food = ko.observable(foodItem);
            self.name = self.food().name;

            self.portions = ko.utils.arrayFilter(self.food().foodPortions, function(foodPortion) {
                return new FoodPortion(foodPortion);
            });

            self.selectedPortion = ko.observable();
        }

        function FoodViewModel() {
            var self = this;

            self.foods = $.map(foodsJson, function(foodItem) {
                return new Food(foodItem)
            });
        }
    </script>

    <div data-bind="foreach: foods">
        <span data-bind="text: name"></span>
        <select data-bind="
            options: portions,
            value: selectedPortion,
            optionsText: function(portion) { return portion.servingSize; }">
        </select>
        <input type="text" data-bind="value: selectedPortion.quantity">
        <br />
    </div>

    <script type="text/javascript">
        ko.applyBindings(new FoodViewModel());
    </script>

</body>

</html>

此外,这里有一个示例 JSON 在应用程序中使用的文件

[{
        "id": "ea17ca42-38d4-7e02-22ea-43b20fc7f3fc",
        "name": "Macaroni",
        "foodPortions": [{
                "id": "69869c2b-efbc-418f-98be-bb5651e595c5",
                "quantity": 1.0,
                "servingSize": "piece",
                "calories": 3.0
            },
            {
                "id": "0d7c01c9-4edd-4da5-91f6-fe18a14ff745",
                "quantity": 100.0,
                "servingSize": "g.",
                "calories": 157.0
            }
        ]
    },
    {
        "id": "c6768773-4e0c-7255-4f0b-0205c7f78f42",
        "name": "Salmon Maki",
        "foodPortions": [{
                "id": "c9c6b7a9-83d0-4dc4-aebb-06948714da65",
                "quantity": 1.0,
                "servingSize": "cup",
                "calories": 305.0
            },
            {
                "id": "cf84c55f-8b91-4419-8868-275d8634f961",
                "quantity": 100.0,
                "servingSize": "g.",
                "calories": 184.0
            },
            {
                "id": "c8c4e813-6a50-4e8e-b5a2-4ae44e846b26",
                "quantity": 1.0,
                "servingSize": "oz (28.34 g.)",
                "calories": 52.0
            },
            {
                "id": "7fac51dd-2592-407e-a4da-6829a6536e6c",
                "quantity": 1.0,
                "servingSize": "piece",
                "calories": 28.0
            }
        ]
    }
]

非常感谢任何帮助! 谢谢

使用 with 绑定将上下文更改为所选项目。

<!-- ko with: selectedPortion -->
<input type="text" data-bind="value: quantity">
<!-- /ko -->

您还应该映射出您希望修改为可观察字段的所有属性。

function FoodPortion(foodPortion) {
    this.id = ko.observable(foodPortion.id);
    this.servingSize = ko.observable(foodPortion.servingSize);
    this.quantity = ko.observable(foodPortion.quantity);
    this.calories = ko.observable(foodPortion.calories);
}

fiddle