Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript ko.当依赖值发生变化时,不进行计算_Javascript_Jquery_Data Binding_Knockout.js_Computed Observable - Fatal编程技术网

Javascript ko.当依赖值发生变化时,不进行计算

Javascript ko.当依赖值发生变化时,不进行计算,javascript,jquery,data-binding,knockout.js,computed-observable,Javascript,Jquery,Data Binding,Knockout.js,Computed Observable,我创造了这把小提琴 该视图不会更新“搜索”和“创建”按钮的启用状态。只有在用户选择产品类时才会发生,但在用户更改组件的值时也必须发生 该视图是一个搜索视图,使用户能够搜索由依赖于所选产品类别的组件标识的产品 视图模型: /// ProductClass function ProductClassModel() { this.Id = 0; this.FullCode = ""; this.Name = ""; this.EntitiClass = "";

我创造了这把小提琴

该视图不会更新“搜索”和“创建”按钮的启用状态。只有在用户选择产品类时才会发生,但在用户更改组件的值时也必须发生

该视图是一个搜索视图,使用户能够搜索由依赖于所选产品类别的组件标识的产品

视图模型:

/// ProductClass
function ProductClassModel() {
    this.Id = 0;
    this.FullCode = "";
    this.Name = "";
    this.EntitiClass = "";

    this.CompClasses = [];
}

/// Component class that is part of a product class
function ComponentClassModel() {
    this.Id = 0;
    this.FullCode = "";
    this.Name = "";
    this.ProductClassId = 0;
    this.ComponentClass = "";
}

/// The product, it is the composition of a product class with values for each of its components
function ProductModel() {
    this.Id = ko.observable(0);
    this.Uid = ko.observable("");
    this.FullCode = ko.observable("");
    this.Name = ko.observable("");
    this.EntitiClass = ko.observable("");
    this.Components = ko.observable([]);
}

/// ComponentValue is a class of component with a value (actually an instance of that class of component)
function ComponentValueModel() {
    this.Id = ko.observable(0);
    this.FullCode = ko.observable("");
    this.Name = ko.observable("");
    this.ProductClassId = ko.observable(0);
    this.ProductId = ko.observable(0);
    this.ComponentClass = ko.observable("");
    this.Value = ko.observable();
}
/// Wrapper of ComponentValueModel with convenient observable properties (We cannot modify the original ComponentValueModel because it is extern)
function ComponentStateViewModel(prodcomp) {
    var self = this;

    console.log("CREA ComponentStateViewModel " + prodcomp);
    self.value = prodcomp.Value();
    self.component = prodcomp;
    self.changed = ko.observable(false);
    self.found = ko.observable(false);
    self.searched = ko.observable(false);
    self.required = true;
    self.isCreatable = ko.computed(function () {
        return self.searched() && !self.found();
    });
    self.isDefined = ko.computed(function () {
        return self.component.Value() !== undefined;
    });

    self.component.Value.subscribe(function () {
        var newval = self.component.Value();
        if (newval !== self.value) {
            self.changed(true);
            self.found(false);
            self.searched(false);
            self.value = newval;
        }
    });
}

/// View model
function ProductViewModel() {

    var self = this;
    self.customerId = ko.observable(111);
    self.prodClasses = ko.observable([]);
    self.currentProdClass = ko.observable();
    self.currentProd = ko.observable();
    self.currentUid = ko.observable(); 
    self.productsFound = ko.observableArray();
    self.componentStates = ko.observableArray();

    self.productFound = ko.computed(function () {
        var prod = self.currentProd();
        return self.prodClassSelected && (prod !== undefined && prod.Uid() !== undefined);
    });

    self.customerSelected = ko.computed(function () {
        return self.customerId() > 0;
    });

    self.prodClassSelected = ko.computed(function () {        
        return self.currentProdClass() !== undefined;
    });

    self.canSearch = ko.computed(function () {
        if (!self.prodClassSelected() || !self.productFound()) {
            return false;
        }

        var inuid = self.currentUid();
        var puid = self.currentProd().Uid();
        if ((inuid !== undefined) && (inuid !== puid) && (inuid.length > 5)) {            
            return true;
        }

        var comps = self.componentStates();
        for (var i = 0; i < comps.length; i++) {
            var c = comps[i];
            if (c.isDefined && !c.searched) {
                return true;
            }
        }

        return false;
    });

    self.canCreate = ko.computed(function () {
        if (!self.prodClassSelected() || self.productFound()) {
            return false;
        }

        var cstates = self.componentStates();
        for (var i = 0; i < cstates.length; i++) {
            var cm = cstates[i];
            if (!cm.component.Value()) {                
                return false;
            }

            if (!cm.isCreatable()) {                
                return false;
            }
        }        
        return true;
    });

    self.clear = function () {
        self.componentStates([]);
        var c = self.currentProdClass();
        if (c !== undefined) {
            self.currentUid(undefined);
            self.currentProd(undefined);
        }
    };

    self.initialize = function (compClassesData) {
            self.prodClasses(compClassesData);
    };

    self.currentUid.subscribe(function () {
        var uid = self.currentUid();
        if (uid === undefined) {
            return;
        }

        var prod = self.currentProd();
        if ((prod === undefined) || (prod.Uid() !== uid)) {
            if (uid.length < 5) {
                return;
            }

            self.currentProd(new ProductModel());
        }
    });

    self.currentProdClass.subscribe(function () {
       self.clear();
        var c = self.currentProdClass();
        if (c === undefined) {
            return;
        }

        var psearch = new ProductModel();
        psearch.FullCode(c.FullCode);
        psearch.Name(c.Name);
        psearch.EntitiClass(c.EntitiClass);
        for (var i = 0; i < c.CompClasses.length; i++) {
            var cca = c.CompClasses[i];
            var comp = new ComponentValueModel();
            comp.FullCode(cca.FullCode);
            comp.Name(cca.Name);
            comp.ProductClassId(cca.ProductClassId);
            comp.ComponentClass(cca.ComponentClass);
            psearch.Components().push(comp);
            self.componentStates.push(new ComponentStateViewModel(comp));
        }
        self.currentProd(psearch);
        self.currentUid(psearch.Uid());

    });

    self.searchProduct = function () {
        var compfilter = [];
        var comps = self.currentProd().Components();
        for (var i = 0; i < comps.length; i++) {
            var c = comps[i];
            if ((c.Value() !== undefined) && (c.Value() !== "")) {
                var filter = new ComponentValueModel();
                filter.FullCode(c.FullCode());
                filter.ComponentClass(c.ComponentClass());
                filter.Value(c.Value());

                compfilter.push(filter);
            }
        }
    };

    self.createProduct = function () {
        // TODO
    };
}
问题在于“搜索”和“创建”按钮。第一个是由一个涉及多个观察值的计算函数启用或禁用的,但我感兴趣的是ComponentValueModel类组件的值。值:

<button data-bind="click: searchProduct, enable: canSearch()">Search</button>
我希望启用或禁用此按钮的代码在ProductViewModel.canSearch计算函数中定义:

self.canSearch = ko.computed(function () {
    if (!self.prodClassSelected() || !self.productFound()) {
        return false;
    }

    var inuid = self.currentUid();
    var puid = self.currentProd().Uid();
    if ((inuid !== undefined) && (inuid !== puid) && (inuid.length > 5)) {
        return true;
    }

    var comps = self.componentStates();
    for (var i = 0; i < comps.length; i++) {
        var c = comps[i];
        if (c.isDefined && !c.searched) {
            return true;
        }
    }

    return false;
});

似乎ko没有通知可观察组件中的值的变化。任何帮助都将不胜感激

尝试删除enable-bind:enable:canSearchI中的括号。如果定义了c,我认为您缺少了对两个组件属性的可观察的取消引用!c、 搜索。第一个是计算的,第二个是可观察的,它们都没有必要访问它们的值。此外,我还必须通过将计算函数ProductViewModel.productFound向上移动来重构代码,使其在调用之前保持不变,否则就不会发生类似self.productFound这样的错误。