开发者

Dependant Observable Array in Knockout JS

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,


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 : []


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/

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜