如何确保所有可观察量都不是未定义的

时间:2014-01-08 19:51:56

标签: knockout.js

我有一个44可观察的淘汰模型。用户为它们选择值并单击提交按钮以将所选值存储在数据库中。如果没有为其中一个observable选择值,我想禁用该按钮。

var TestModel = function() {
    self.Feedback1 = ko.observable();
    self.Feedback2 = ko.observable();
    ..
    self.Feedback44 = ko.observable();
    self.IsEnabled = ko.observable(false);
    self.Feedback1.subscribe(function(){
       if (self.Feedback1() != undefined && .... self.Feedback44() != undefined) {
          self.IsEnabled(true);
       } else {
          self.IsEnabled(false); 
       } 
   };
   .
   .
    self.Feedback44.subscribe(function(){
       if (self.Feedback1() != undefined && .... self.Feedback44() != undefined) {
          self.IsEnabled(true);
       } else {
          self.IsEnabled(false); 
       } 
   };


};

<button data-bind="click: SubmitEvaluation,enable:IsEnabled">Submit Evaluation</button>

4 个答案:

答案 0 :(得分:1)

将对属性的引用添加到数组中:

self.submitableProperties = [self.Feedback1, self.Feedback2, ..., self.Feedback44];

然后,扫描您的属性变得更加容易。

for (var i = 0; i < self.submitableProperties.length; i++) {
    self.submitableProperties[i].subscribe(checkEnabled);
}

function checkEnabled() {
    var anyUndefined = false;
    for (var i = 0; i < self.submitableProperties.length; i++) {
        if (self.submitableProperties[i]() === undefined) {
            anyUndefined = true;
            return;
        }
    }
    self.IsEnabled(!anyUndefined);
}

答案 1 :(得分:1)

要完成您尝试使用最少量代码执行的操作,我将创建一个循环遍历viewmodel的所有可观察对象的计算器。

        self.isEnabled = ko.computed(function() {
            for (p in self) {
                if (ko.isObservable(self[p])) {
                    if (self[p]() === null || self[p]() === undefined)
                        return false;
                }
            }
            return true;
        });

答案 2 :(得分:1)

我认为Marius建议的解决方案是最干净的方法。但是,检查可观察值是否为null或未定义是有点愚蠢 - 如果其中一个反馈可观察对象是空字符串,或者是否存在与表单无关但未定义的另一个可观察对象,该怎么办?在这两种情况下,您将遇到建议的解决方案的问题。因此,我们希望检测反馈可观察量并检查它们。有几种方法可以做到这一点,这里有几个:

  1. 命名约定,所有反馈属性名称都包含“反馈”作为子字符串
  2. 以编程方式将反馈可观察量添加到数组中(如果没有特别的理由将它们命名)
  3. 在对象中添加所有反馈属性,该对象是您查看模型的属性
  4. 在下面的jsfiddle中,我采用了第一种方法 http://jsfiddle.net/pardahlman/dz7UH/

    self.AllQuestionsAnswered = ko.computed(function () {
        for (p in self) {
            if (ko.isObservable(self[p])) {
                var isFeedback = p.indexOf('Feedback') != -1;
                if (!isFeedback) {
                    continue;
                }
                var valueOfObservable = self[p]();
                if (!valueOfObservable) {
                    return false;
                }
    
            }
        }
    
        return true;
    });
    

答案 3 :(得分:1)

一个很好的方法,可以帮助您的应用程序的许多其他部分使用knockout.validation库:

https://github.com/Knockout-Contrib/Knockout-Validation

我创建了一个小提琴,演示了如何将其应用于您的场景。

http://jsfiddle.net/jiggle/2xAS7/

HTML:

<fieldset>
    <legend>User: <span data-bind='text: errors().length'></span> errors</legend>
    <label>Feedback 1: <input data-bind='value: feedback1' required/></label>
    <label>Feedback 2: <input data-bind='value: feedback2' required/></label>    

    <label>
        Subscriptions: 
        <select data-bind='value: feedback3, options: feedback3Options, optionsCaption: "Choose one..."' required></select>
    </label>
   <label>Feedback 4: <input data-bind='value: feedback4' required/></label>   
    <label>Feedback 5: <input data-bind='value: feedback5' required/></label>   
    <label>Feedback 6: <input data-bind='value: feedback6' required/></label>   
        <label>Feedback 7: <input data-bind='value: feedback7' required/></label>   
</fieldset>
<button type="button" data-bind='click: submit'>Submit</button>

        <button type="button" data-bind='click: submit, enable:isComplete'>Submit (disabled if not complete)</button>

        <button type="button" data-bind='click: submit, enable:errors().length===0'>Submit (disabled if not complete)</button>

<br />
<br />

       Display inline error messages? <input type="checkbox" data-bind='click: toggleInlineErrors,checked:showInlineErrors'/>

代码:

ko.validation.rules.pattern.message = 'Invalid.';


ko.validation.configure({
    registerExtenders: true,
    messagesOnModified: true,
    insertMessages: true,
    parseInputAttributes: true,  //this is 'true' to read the 'required' attribute in your html
    messageTemplate: null
});


var viewModel = {
    feedback1: ko.observable(),  //required attribute is set in the HTML
    feedback2: ko.observable(),  //required attribute is set in the HTML
    feedback3: ko.observable(),  //required attribute is set in the HTML
    feedback4: ko.observable(),  //required attribute is set in the HTML
    feedback5: ko.observable(),  //required attribute is set in the HTML
    feedback6: ko.observable(),  //required attribute is set in the HTML
    feedback7: ko.observable().extend({ required: true }), //or add the required attribute when you create the observable
    feedback3Options: ['Technology', 'Music'],

    submit: function () {
        if (viewModel.errors().length == 0) {
            alert('Thank you.');
        } else {

            viewModel.errors.showAllMessages(this.showInlineErrors());
            alert('Please check your submission.');
        }
    }
};

viewModel.showInlineErrors = ko.observable(true);
viewModel.errors = ko.validation.group(viewModel);

viewModel.isComplete = ko.computed(function(){
    return viewModel.errors().length === 0
});

viewModel.toggleInlineErrors = function () {  
    viewModel.errors.showAllMessages(false);
    return true;
};

addEventListener('load', function () {
ko.applyBindings(viewModel);
});

关键是ko.validation.group(viewModel),它将您的所有observable分组到一个组中,当您对viewmodel进行更改时,该组将被不断地(可观察)进行评估。

话虽如此,您可以进行数据绑定:&#39;启用:viewModel.errors.length === 0,点击:yourClickHandler&#39;或者创建一个计算的observable,如果没有错误,则返回true。

小提琴演示了两种选择。

它是一个优秀的库,非常强大,我创建的小提琴也演示了如何切换内联错误,只是给出一个整体消息(当你提交时),或突出显示缺少的内联条目,以便用户可以看到缺少的选项在哪里(如果您有44个用户需要完成的项目,可能非常有用!)。

希望有所帮助

(只包括kendo.validation.js(来自上面的github参考)到你的页面/包/模块,你可以开始使用它了)