如何在Knockoutjs中将categoryId从一个ViewModel传递到另一个ViewModel - 错误categoryId undefined

时间:2016-05-21 17:47:18

标签: twitter-bootstrap knockout.js asp.net-mvc-5

我有两个Bootstrap下拉列表,当我在第一个中选择一个类别时,第二个应该根据第一个的categoryId填充。我尝试使用subscribe函数将reportId从reportCategoryViewModel传递给reportTypeViewModel,但它没有按预期工作,我得到错误categoryId undefined。

var shouter = new ko.subscribable();
function reportCategoryViewModel() {
...
self.selectedReportCategoryName = ko.observable();
self.selectReportCategory = function (reportCategoryList) {
    self.selectedReportCategoryName(reportCategoryList.reportCategoryName);
    var categoryId = reportCategoryList.reportCategoryId;

此代码工作正常,我使用警报进行了测试,当我选择一个类别时,警报会显示正确的categoryId:

    alert("reportCategoryViewModel - categoryId " + categoryId);

    self.reportCategoryId.subscribe(function (categoryId) {
        shouter.notifySubscribers(categoryId, "categoryIdForSelectingTypes");
    });
};

function reportTypeViewModel() {
...
self.selectedCategoryId = ko.observable();
self.reportTypes = ko.observableArray();
self.selectedReportType = ko.observable();
self.selectReportType = function (reportTypeList) {
    self.selectedReportType(reportTypeList.reportTypeName);
};

如果我在下面的shouter中正确传递categoryId,我不会感到沮丧:

shouter.subscribe(function (categoryId) {
    self.selectedCategoryId(categoryId);
}, self, "categoryIdForSelectingTypes");

发生错误是因为下面的selft.selectedCategoryId()不包含有效的categoryId:

var uriReportType = 'api/reporttypes/' + self.selectedCategoryId();
var reportTypeArray = [];
$.getJSON(uriReportType)
    .done(function (data) {
        $.each(data, function (index, item) {
            reportTypeArray.push(item);
            self.reportTypes(reportTypeArray);
        });
    });
}
$(document).ready(function () {
var masterViewModel = (function () {
    this.reportCategoryViewModel = new reportCategoryViewModel();
    this.reportTypeViewModel = new reportTypeViewModel();
})();

ko.applyBindings(masterViewModel);
});

Here is the JsFiddle code

错误:GET http://localhost:49758/api/reporttypes/undefined 400(错误请求)

1 个答案:

答案 0 :(得分:0)

KO邮箱示例

我有一个更新的小提琴https://jsfiddle.net/0uz3yo5g/3/和ko.postbox。

首先加载ko.postbox,然后在创建observable时,设置一个发布渠道,例如

self.reportCategoryId = ko.observable().publishOn('reportCategoryID');

我已经注释了shouter代码 - 最好不要乱用全局空间并坚持使用vm到vm通信(通过邮箱)或集中(根据我的github示例)

您需要接收事件的所有内容都是ko.postbox.subscribe,例如

ko.postbox.subscribe('reportCategoryID', function(categoryId) {
    self.selectedCategoryId(categoryId);
    alert("categoryId VM2" + categoryId);
}, self, "categoryIdForSelectingTypes");

使用ViewModel的中央服务提供商

我倾向于使用中央服务提供商(singleton)来保存数据并提供操作数据的功能或通过api等获取新功能。

例如

const ko = require('knockout');
const CentralState = {
    signIn : componentName => signIn(componentName),
    signedInComponents : ko.observableArray([]),
};
const signIn = (componentName) => {
    if (CentralState.signedInComponents().indexOf(componentName) < 0) {
        CentralState.signedInComponents.push(componentName);
    }
};
module.exports = CentralState;

您可以在此处看到https://github.com/brianlmerritt/knockout-babel-browserify-gulp设置了两个服务提供商(一个用于api,一个用于州),包括Gulp和Babel转换,因此您可以使用新的Javascript。

无论哪种方式,您只需订阅中央服务提供商observable或ko.postbox&#39;频道&#39;在其他视图模型更改影响您时获取更新。