Uncaught TypeError: Unable to process binding "if" with knockout

Uncaught TypeError: Unable to process binding "if" with knockout

我只是想创建一些复选框和输入,以从数据库中获取数据并在编辑后将其保存回数据库。但我收到以下错误:

Uncaught TypeError: Unable to process binding "if: function(){return $root.editAlarmValues }" Message: Unable to process binding "enable: function(){return $root.editAlarmValues().setAlarmValues() }" Message: $root.editAlarmValues(...).setAlarmValues is not a function

我不确定我做错了什么。我检查了控制台,值被正确映射到数组,但它们似乎没有绑定到视图。任何帮助将不胜感激!

代码如下:

        <!--ko if: $root.editAlarmValues -->
       
            <div class="row">
                <div class="col-md-6">
                    <input type="checkbox" data-bind="iCheck: $root.editAlarmValues().setAlarmValues" class="large-check"/>
                </div>
            </div>

            <div class="row">
                <div class="col-md-5 form-inline">
                    <input type="checkbox" data-bind="iCheck: $root.editAlarmValues().setOutputCurrentPPLowValue, enable: $root.editAlarmValues().setAlarmValues()" class="large-check"/>
                            <input type="text" id="OutputCurrentPPLowValue" data-bind="value: $root.editAlarmValues().outputCurrentPPLowValue, enable: $root.editAlarmValues().setOutputCurrentPPLowValue()" class="form-control" maxlength="30" />
                 </div>
            </div>
            <div class="row">
                <div class="col-md-12">
                    <div class="pull-right">

                        <button type="button" class="btn btn-primary btn-flat" data-bind="event: {click: $root.editSave}">Save</button>
                    </div>
                </div>
            </div>

            <!-- /ko -->

和脚本:

 var AlarmsViewModel = function (wellID) {

        function EditAlarms(setAlarmValues, setOutputCurrentPPLowValue, outputCurrentPPLowValue) {
            var self = this;
            self.setAlarmValues = ko.observable(setAlarmValues);
            self.setOutputCurrentPPLowValue = ko.observable(setOutputCurrentPPLowValue);
            self.outputCurrentPPLowValue = ko.observable(outputCurrentPPLowValue);
        }

        var self = this;
        self.wellID = ko.observable(wellID);
        self.editAlarmValues = ko.observableArray(); 
     
        self.init = function () {
            self.editAlarmInit();
        };

        self.editAlarmInit = function () {
            APIHelper.getData("/api/alarmapi/EditAlarms?wellID=" + self.wellID(), self.editAlarmsCallback, "");
        };

        self.editAlarmsCallback = function (data) {
            //Map results
            var temp = $.map(data.result, function (item) {
                return new EditAlarms(item.setAlarmValues, item.setOutputCurrentPPLowValue, item.outputCurrentPPLowValue);
            });
            self.editAlarmValues(temp);                
        };

        self.editSave = function () {
            var jsonData = ko.toJSON(self.editAlarmValues);        
            APIHelper.postData("/api/alarmapi/EditAlarmsPost", jsonData);
        };

        self.init();
    };

    var wellID = @ViewBag.WellID;
   
    ko.bindingHandlers.iCheck = {
        init: function (el, valueAccessor) {
            var observable = valueAccessor();
            $(el).on("ifChanged", function () {
                observable(this.checked);
            });
        },

        update: function (el, valueAccessor) {
            var val = ko.utils.unwrapObservable(valueAccessor());
            if (val) {
                $(el).iCheck('check');
            } else {
                $(el).iCheck('uncheck');
            }
        }
    };


    var vm = new AlarmsViewModel(wellID);
    ko.applyBindings(vm);

您不想要 <!-- ko if: editAlarmValues -->,您想要 <!-- ko foreach: editAlarmValues -->。当目标数组为空时,foreach不会运行,所以它从根本上实现了相同的功能。

foreach 中,绑定上下文是有问题的 EditAlarms 对象,因此您应该直接引用它的属性(iCheck: setOutputCurrentPPLowValue 而不是 iCheck: $root.editAlarmValues().setOutputCurrentPPLowValue)。

还要考虑你的命名。 EditAlarms 不是单个对象的好名称。前缀 set... 应该指的是一个设置某些东西的方法。在这种情况下,它只是一个可观察的 属性。 setAlarmValues 应该被称为 alarmValues,因为它不是一个数组,它实际上可能应该被称为 alarmValue。等等。

<!-- ko foreach: editAlarmValues -->
<div class="row">
    <div class="col-md-6">
        <input type="checkbox" data-bind="iCheck: setAlarmValues" class="large-check">
    </div>
</div>
<div class="row">
    <div class="col-md-5 form-inline">
        <input type="checkbox" class="large-check" data-bind="
            iCheck: setOutputCurrentPPLowValue,
            enable: setAlarmValues
        ">
        <input type="text" id="OutputCurrentPPLowValue" class="form-control" maxlength="30" data-bind="
            value: outputCurrentPPLowValue,
            enable: setOutputCurrentPPLowValue
        ">
     </div>
</div>
<div class="row">
    <div class="col-md-12">
        <div class="pull-right">
            <button type="button" class="btn btn-primary btn-flat" data-bind="click: $root.editSave">Save</button>
        </div>
    </div>
</div>
<!-- /ko -->

修改后的 JS 代码(将绑定处理程序定义移至顶部,不要嵌套视图模型)

ko.bindingHandlers.iCheck = {
    init: function (el, valueAccessor) {
        var observable = valueAccessor();
        $(el).on("ifChanged", function () {
            observable(this.checked);
        });
    },
    update: function (el, valueAccessor) {
        var val = ko.unwap(valueAccessor());
        $(el).iCheck(val ? 'check' : 'uncheck');
    }
};

function EditAlarms(setAlarmValues, setOutputCurrentPPLowValue, outputCurrentPPLowValue) {
    this.setAlarmValues = ko.observable(setAlarmValues);
    this.setOutputCurrentPPLowValue = ko.observable(setOutputCurrentPPLowValue);
    this.outputCurrentPPLowValue = ko.observable(outputCurrentPPLowValue);
}

function AlarmsViewModel(wellID) {
    var self = this;

    self.wellID = ko.observable(wellID);
    self.editAlarmValues = ko.observableArray();

    self.editAlarmInit = function () {
        APIHelper.getData("/api/alarmapi/EditAlarms?wellID=" + self.wellID(), function (data) {
            var alarms = data.result.map(item => new EditAlarms(
                item.setAlarmValues,
                item.setOutputCurrentPPLowValue,
                item.outputCurrentPPLowValue
            ));
            self.editAlarmValues(alarms);
        });
    };
    self.editSave = function () {
        APIHelper.postData("/api/alarmapi/EditAlarmsPost", ko.toJSON(self.editAlarmValues));
    };

    self.editAlarmInit();
}

var vm = new AlarmsViewModel(@ViewBag.WellID);
ko.applyBindings(vm);