多视图模型绑定,带绑定的共享错误对话框

时间:2014-07-09 21:26:38

标签: data-binding knockout.js

我在一个页面上有两个视图模型,它们对应于不同选项卡上的两组不同内容。

我将每个视图模型绑定到标记中对应的根元素。但是,我希望有一个标准的通用部分,任何一个模型都可以使用(我的方案中母版页上的错误的一般模态对话框),它不包含在任何绑定的根元素中。

我应该如何处理?我应该将多个模型嵌套在一个主视图模型中,还是不能绑定到特定元素?我是淘汰赛的新手,所以我对所有的建议持开放态度。

这显示了我想要完成的内容减去重复的模态部分。小提琴:http://jsfiddle.net/z3wGr/3/

JS:

ko.bindingHandlers.errorModal = {
    update: function (element, valueAccessor) {
        var valueAccessorValue = valueAccessor();
        var value = ko.utils.unwrapObservable(valueAccessorValue);
        if (value.length > 0) {
            // $(element).modal('show');
            console.log("would be showing modal here");
        } else {
            // $(element).modal('hide');
        }
    }
};

var sectionOneViewModel = {
    sectionOne: ko.observable("section one"),
    errors: ko.observableArray([]),
    aSectionOneMethod: function (self) {
        // make AJAX call here
        // error returns from server
        // push error into array triggering modal because of custom binding handler
        self.errors.push({
            errorText: "something went wrong."
        })
    }
}

var sectionTwoViewModel = {
    sectionTwo: ko.observable("section two"),
    errors: ko.observableArray([]),
    aSectionTwoMethod: function (self) {
        // make AJAX call here
        // error returns from server
        // push error into array triggering modal because of custom binding handler
        self.errors.push({
            errorText: "something went wrong."
        })
    }
}

ko.applyBindings(sectionOneViewModel, document.getElementById('section-one'));
ko.applyBindings(sectionTwoViewModel, document.getElementById('section-two'));

HTML:

<div id="section-one"> 
    <span data-bind="text: sectionOne"></span>
    <br />
    <input type="button" value="call section one function" data-bind="click: aSectionOneMethod" />
    <!-- This is a generic modal that all of my viewmodels use to show errors, I don't want to include it in every binding section -->
    <div id="generic-error-modal" data-bind="errorModal: errors">
        <p>I'm a modal dialog that would actually only display when an error is returned from the server after an AJAX call.</p>
        <ul data-bind="foreach: errors">
            <li data-bind="text: errorText"></li>
        </ul>
    </div>
</div>

<div id="section-two"> 
    <span data-bind="text: sectionTwo"></span>
    <br />
    <input type="button" value="call section two function" data-bind="click:             aSectionTwoMethod" />
    <!-- This is a generic modal that all of my viewmodels use to show errors, I don't want to include it in every binding section -->
    <div id="generic-error-modal" data-bind="errorModal: errors">
        <p>I'm a modal dialog that would actually only display when an error is returned from the server after an AJAX call.</p>
        <ul data-bind="foreach: errors">
            <li data-bind="text: errorText"></li>
        </ul>
    </div>
</div>

**修改:基于以下答案和评论的工作示例:http://jsfiddle.net/z3wGr/6/

1 个答案:

答案 0 :(得分:1)

我建议让一个viewModel嵌套其他两个模型。您可能需要将错误传递给嵌套模型,以便它们可以与错误进行交互。

我还建议您为模型和新对象使用函数。

这是一个缩减版本。我还没有对其进行测试,因此可能会出现一些小错误:

var ViewModel = function() {
    var self = this;

    self.errors = new Errors();

    self.sectionOne = new SectionOneViewModel(self.errors);
    self.sectionTwo = new SectionTwoViewModel(self.errors);
};

var SectionOneViewModel = function(errors) {
    var self = this;

    self.sectionOne = ko.observable("section one");
    self.errors = errors;

    //this is how to add an error
    self.errors.add("This is an error");
};

var SectionTwoViewModel = function(errors) {
    var self = this;

    self.sectionTwo = ko.observable("section two");
    self.errors = errors;
};

var Errors = function() {
    ver self = this;

    self.errors = ko.observableArray();

    self.add = function (errorText) {
        self.errors.push(new Error(errorText));
    };

    self.clear = function() {
        self.errors.removeAll();
    };
};

var Error = function(errorText) {
    var self = this;

    self.errorText = errorText;
};