Knockout JS 中的依赖可观察数组

发布于 2024-12-07 07:11:50 字数 3411 浏览 0 评论 0原文

我已经开始使用 knockoutjs 并进行一些简单的绑定/依赖绑定。 我的目标是根据另一个 列表。两者都是通过对我的 asp.net web 服务的 ajax 调用加载的。

所以我有两个

<select id="make" data-bind="options: availableMakes, value: selectedMake, optionsText: 'text', optionsCaption: 'Choose a make'"></select>
<select id="model" data-bind="options: availableModels, value: selectedModel, optionsText: 'text', optionsCaption: 'Choose a model'"></select>

然后我的 javascript 看起来像这样:

$(function () {

            // creating the model
            var option = function (text, value) {
                this.text = text;
                this.value = value;
            }

            // creating the view model
            var searchModel = {
                availableMakes: ko.observableArray([]),
                availableModels: ko.observableArray([]),
                selectedMake: ko.observable(),
                selectedModel: ko.observable()
            }

            // adding in a dependentObservable to update the Models based on the selected Make
            searchModel.UpdateModels = ko.dependentObservable(function () {
                var theMake = searchModel.selectedMake() ? searchModel.selectedMake().text : '';
                if (theMake != '') {
                    $.ajax({
                        url: "/data/service/auction.asmx/GetModels",
                        type: 'GET',
                        contentType: "application/json; charset=utf-8",
                        data: '{make:"' + theMake + '"}',
                        success: function (data) {
                            var makes = (typeof data.d) == 'string' ? eval('(' + data.d + ')') : data.d;
                            var mappedModels = $.map(makes, function (item) {
                                return new option(item.text, item.value);
                            });
                            searchModel.availableModels(mappedModels);
                        },
                        dataType: "json"
                    });
                }
                else {
                    searchModel.availableModels([]);
                }
                return null;
            }, searchModel);

            // binding the view model
            ko.applyBindings(searchModel);

            // loading in all the makes
            $.ajax({
                url: "/data/service/auction.asmx/GetMakes",
                type: 'GET',
                contentType: "application/json; charset=utf-8",
                data: '',
                success: function (data) {
                    var makes = (typeof data.d) == 'string' ? eval('(' + data.d + ')') : data.d;
                    var mappedMakes = $.map(makes, function (item) {
                        return new option(item.text, item.value);
                    });
                    searchModel.availableMakes(mappedMakes);
                },
                dataType: "json"
            });

        });

目前这按预期工作,但我认为我做错了,因为代码看起来很长,我可以这样做无需在更少的代码中使用knockoutjs。 另外,我加载 availableModels 的方式显然不正确,因为我使用的是一个名为 UpdateModels 的 dependentObsevable,我添加它是为了加载 availableModels< /code> 基于 selectedMake().text 的值

我希望这是有道理的,你能指出这个的改进版本吗?或者简单地告诉我如何根据“品牌”选择重新加载模型?

非常感谢,

I have started to play around with knockoutjs and do some simple binding/dependant binding.
My goal is to have 1 <select> list populated based on the value of another <select> list. Both are being loaded from an ajax call to my asp.net webservice.

So I have two <select> lists

<select id="make" data-bind="options: availableMakes, value: selectedMake, optionsText: 'text', optionsCaption: 'Choose a make'"></select>
<select id="model" data-bind="options: availableModels, value: selectedModel, optionsText: 'text', optionsCaption: 'Choose a model'"></select>

Then my javascript looks like this:

$(function () {

            // creating the model
            var option = function (text, value) {
                this.text = text;
                this.value = value;
            }

            // creating the view model
            var searchModel = {
                availableMakes: ko.observableArray([]),
                availableModels: ko.observableArray([]),
                selectedMake: ko.observable(),
                selectedModel: ko.observable()
            }

            // adding in a dependentObservable to update the Models based on the selected Make
            searchModel.UpdateModels = ko.dependentObservable(function () {
                var theMake = searchModel.selectedMake() ? searchModel.selectedMake().text : '';
                if (theMake != '') {
                    $.ajax({
                        url: "/data/service/auction.asmx/GetModels",
                        type: 'GET',
                        contentType: "application/json; charset=utf-8",
                        data: '{make:"' + theMake + '"}',
                        success: function (data) {
                            var makes = (typeof data.d) == 'string' ? eval('(' + data.d + ')') : data.d;
                            var mappedModels = $.map(makes, function (item) {
                                return new option(item.text, item.value);
                            });
                            searchModel.availableModels(mappedModels);
                        },
                        dataType: "json"
                    });
                }
                else {
                    searchModel.availableModels([]);
                }
                return null;
            }, searchModel);

            // binding the view model
            ko.applyBindings(searchModel);

            // loading in all the makes
            $.ajax({
                url: "/data/service/auction.asmx/GetMakes",
                type: 'GET',
                contentType: "application/json; charset=utf-8",
                data: '',
                success: function (data) {
                    var makes = (typeof data.d) == 'string' ? eval('(' + data.d + ')') : data.d;
                    var mappedMakes = $.map(makes, function (item) {
                        return new option(item.text, item.value);
                    });
                    searchModel.availableMakes(mappedMakes);
                },
                dataType: "json"
            });

        });

Currently this works as expected, but I think that I am doing this wrong as the code looks pretty long, and I could do this without using knockoutjs in less code.
Also the way that I am loading up the availableModels is obviously not correct because I am using a dependentObsevable called UpdateModels which I added in order to load up the availableModels based on the value of selectedMake().text

I hope this makes sense and you can point out an improved version of this? Or tell me simply How do I reload the Models based on the Make selection?

Many Thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笔落惊风雨 2024-12-14 07:11:51

我认为你的代码看起来很正常。对于 UpdateModels dependentObservable,您实际上可以使用对 selectedMake 的手动订阅,如下所示:

searchModel.selectedMake.subscribe(function (newMake) {
    if (newMake) {
        //ajax request
    }
    else {
        searchModel.availableModels([]);
    }
}, searchModel);

这不会更改功能,只是订阅单个可观察更改的更明确的方式。

您还可以选择在绑定中使用 optionsValue: 'text' (或 'value'),并且您的 selectedMake 将直接设置为文本或值。

如果您的模型是 make 对象的子对象,那么您甚至可以将模型绑定到 selectedMake().models (需要防止 selectedMake 为空,这可以使用 DO 来完成,1.3控制流绑定,还是像 selectedMake().models : [] 那样内联?

I think that your code looks pretty normal. For the UpdateModels dependentObservable, you can actually use a manual subscription to selectedMake like:

searchModel.selectedMake.subscribe(function (newMake) {
    if (newMake) {
        //ajax request
    }
    else {
        searchModel.availableModels([]);
    }
}, searchModel);

This would not change the functionality, just a more explicit way to subscribe to a single observable changing.

You could also choose to use optionsValue: 'text' (or 'value') in the binding and your selectedMake would be set to the text or value directly.

If your models were children of the make objects, then you could even bind the models to selectedMake().models (would need to protect against selectedMake being null, which could be done using a DO, the 1.3 control flow binding, or inline like selectedMake() ? selectedMake().models : []

红尘作伴 2024-12-14 07:11:51

我同意瑞安的回答。

稍微考虑一下相关的切线,我对其进行了一些重构,以不使用 ajax 并简化示例(您可以随时将其添加回来)。但这是一个小提琴,它演示了您希望如何处理一些示例数据。

http://jsfiddle.net/johnpapa/vGg2h/

I agree with Ryan's answer.

Taking it a bit on a related tangent, I refactored it a bit to not use ajax and to simplify the example (you can always add that back in). But here is a fiddle that demonstrates what you are looking to do with some sample data.

http://jsfiddle.net/johnpapa/vGg2h/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文