我创建了这个小提琴http://jsfiddle.net/mj9f9/4/
视图不会更新按钮“搜索”和“创建”的启用状态。只有在用户选择产品类时才会发生,但必须在用户更改组件的值时发生。
该视图是一个搜索视图,使用户能够搜索由依赖于所选产品类别的组件标识的产品。
视图模型:
/// 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
};
}
问题在于搜索和创建按钮。第一个是由一个涉及多个observable的计算函数启用或禁用的,但我感兴趣的是ComponentValueModel.Value类的一个组件的值:
<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没有通知可观察组件中值的变化。值。任何帮助将不胜感激。