Knockout JS选项与选定选项绑定

时间:2014-10-15 09:37:56

标签: jquery html knockout.js

我有这个令人难以置信的问题。 我的页面上有2个下拉列表,如下所示:

<div class="form-group">
    <label class="control-label">Current competition</label>
    <select class="form-control" data-bind="options: competitions, optionsText: 'Name', value: selectedCompetition, optionsCaption: 'Choose...'"></select>
</div>

<div class="form-group">
    <label class="control-label">Style</label>
    <select class="form-control" data-bind="options: styles, optionsText: 'Name', value: selectedStyle, optionsCaption: 'Choose...'"></select>
</div>

比赛一个人完美运作,但是除了选择...... 之外,从不选择任何东西。 我的视图模型有一个初始化方法,如下所示:

function init() {
    $.get(competitionsUrl)
        .done(function (data) {
            $.each(data, function (i, competition) {                    
                self.competitions.push(competition);

                if (competition.Current) {
                    self.selectedCompetition(competition);
                    self.selectedStyle(competition.Style);
                }
            });
        })
        .always(function () {
            self.loading(false);
        })
        .fail(common.handleError);

    $.get(stylesUrl)
        .done(function (data) {
            $.each(data, function (i, style) {
                self.styles.push(style);
            });
        })
        .fail(common.handleError);
};

现在,这就是有趣的部分。如果我在设置之后直接放置 console.log(self.selectedStyle()),我会得到 undefined 在控制台中。花了一段时间,但我意识到如果我改变我的风格选择到这个:

<div class="form-group">
    <label class="control-label">Style</label>
    <select class="form-control" data-bind="options: styles, optionsText: 'Name'"></select>
</div>

然后我的控制台返回正确的选定样式。 所以,正在发生的事情是,选择框实际上是将 selectedStyle 设置为undefined。 为什么它只发生在风格下拉,而不是比赛让我困惑。

之前有没有人经历过这种情况,或许知道解决方案?

以防万一,这是我的整个视图模型。

function SettingsViewModel(app, dataModel) {
    var self = this,
        competitionsUrl = "/api/competitions",
        stylesUrl = "/api/styles";

    // Private operations
    function init() {
        $.get(competitionsUrl)
            .done(function (data) {
                $.each(data, function (i, competition) {                    
                    self.competitions.push(competition);

                    if (competition.Current) {
                        self.selectedCompetition(competition);
                        self.selectedStyle(competition.Style);
                    }
                });
            })
            .always(function () {
                self.loading(false);
            })
            .fail(common.handleError);

        $.get(stylesUrl)
            .done(function (data) {
                $.each(data, function (i, style) {
                    self.styles.push(style);
                });
            })
            .fail(common.handleError);
    };

    function uploadProgress(e, progressBar) {
        if (e.lengthComputable) {
            var percentComplete = Math.round(e.loaded * 100 / e.total).toString();

            common.setProgressValue(progressBar, percentComplete);
        }
        else {
            toastr["warning"](uploadProgressErrorMessage);

            common.setProgressValue(progressBar, 0);
        }
    };

    function uploadComplete(file, filePath) {
        console.log(file);
        console.log(filePath);
    };

    // Data
    self.styles = ko.observableArray();
    self.competitions = ko.observableArray();
    self.selectedStyle = ko.observable();
    self.selectedCompetition = ko.observable();

    // State
    self.loading = ko.observable(true);
    self.saving = ko.observable(false);

    // Operations
    self.selectedCompetition.subscribe(function (vm, event) {
        if (!self.loading()) {
            self.selectedCompetition().Current = true;

            self.save();
        }
    });

    self.selectedStyle.subscribe(function (vm, event) {
        if (vm) {
            self.selectedCompetition().StyleId = vm.Id;
        }
    });

    self.uploadLogo = function (e) {        
        if (e.target.files && e.target.files[0]) {
            var file = e.target.files[0];

            common.getUrl().done(function (url) {
                common.generateFolders(0).done(function (folders) {
                    common.uploadFile(url, file, folders, ".logo-progress", uploadProgress, uploadComplete);
                });
            }).fail(function () {
                toastr["error"]("Failed to get the upload url.");
            });
        }
    };

    self.save = function () {
        self.saving(true);

        console.log(self.selectedCompetition());

        $.ajax({
            url: competitionsUrl,
            method: "POST",
            data: self.selectedCompetition()
        }).done(function () {
            // Do nothing
        }).always(function () {
            self.saving(false);
        }).fail(common.handleError);
    };

    init();

    return self;
};

app.addViewModel({
    name: "Settings",
    bindingMemberName: "settings",
    factory: SettingsViewModel
});

任何帮助都将一如既往地受到高度赞赏:)

1 个答案:

答案 0 :(得分:1)

正如汉斯所说,这是因为我如何填充我的风格。 我将我的init方法更改为:

function init() {
    $.get(competitionsUrl)
        .done(function (data) {
            var styleId = 0;

            $.each(data, function (i, competition) {                    
                self.competitions.push(competition);

                if (competition.Current) {
                    self.selectedCompetition(competition);
                    styleId = competition.Style.Id;
                }
            });

            $.get(stylesUrl)
                .done(function (data) {
                    $.each(data, function (i, style) {
                        self.styles.push(style);

                        if (style.Id == styleId) {
                            self.selectedStyle(style);
                        }
                    });
                })
                .always(function () {
                    self.loading(false);
                })
                .fail(common.handleError);
        })
        .fail(common.handleError);
};

解决了这个问题。