我陷入了这一点,无法继续。
我正在以这种方式为搜索表单创建一个ViewModel:
var viewModel = new SearchViewModel("Api/Vehicle", "Vehicles");
ko.applyBindings(viewModel);
稍后当用户点击查找按钮时,它会触发find方法(在此处简化):
self.Find = function (predicate) {
var query = breeze.EntityQuery
.from(self.actionName)
.where(predicate);
var promisse = self.manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
}
query *方法只将数据放在Knockout.js可观察数组中:
function querySucceeded(data) {
data.results.forEach(function (item) {
self.results.push(item);
});
return true;
}
function queryFailed(error) {
var erroboj = { message: error.message };
self.errors.push(erroboj);
return false;
}
问题是,从不调用querySucceeded,并且Knockout.js的数据永远不会更新,因此会激活数据绑定。
我做错了什么?
这是ViewModel。有点不完整和模糊。 我想我没有正确理解微风查询的承诺:
/*global $, jQuery, ko, breeze, bootstrap */
function SearchViewModel(serviceName, actionName) {
"use strict";
var self = this;
self.serviceName = serviceName;
self.actionName = actionName;
self.errors = ko.observableArray([]);
self.results = ko.observableArray([]);
self.CreateEntity = function (entityTypeName) {
var entityType = self.manager.metadataStore.getEntityType(entityTypeName),
newEntity = entityType.createEntity();
return self.manager.addEntity(newEntity);
};
function querySucceeded(data) {
// Here the function I want to run
data.results.forEach(function (item) {
self.results.push(item);
});
return true;
}
function queryFailed(error) {
var erroboj = { message: error.message };
self.errors.push(erroboj);
return false;
}
function addError(errorMessage) {
var erroobj = { message: errorMessage };
self.errors.push(erroobj);
}
function NoFilterDefined(Condition) {
var s = "Find(): Funcao Filter() not implemented:";
addError(s);
Condition = null;
throw new Error(s);
}
try {
self.Filter = NoFilterDefined;
self.Find = function () {
debugger;
var Condition = breeze.Predicate;
var predicate;
self.errors.removeAll();
try {
predicate = self.Filter(Condition);
} catch (errorf) {
var sf = "Find(): Error calling Filter() in {actionName}: {error}";
sf = sf.replace("{error}", errorf.message);
sf = sf.replace("{actionName}", predicate.toString());
addError(sf);
throw new Error(sf);
}
var query = breeze.EntityQuery
.from(self.actionName)
.where(predicate);
try {
debugger;
var promisse = self.manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
// Here I suppose the .then(querySucceeded) already was called
} catch (errore) {
var se = "Find(): Erro calling query in {actionName}: {error}";
se = se.replace("{error}", errore.message);
se = se.replace("{actionName}", self.actionName);
addError(se);
throw new Error(se);
}
};
self.FetchMetadata = function () {
//self.manager.fetchMetadata() // not working?
// .fail(self.queryFailed);
var query = breeze.EntityQuery
.from(actionName)
.where("1", "==", "0"); // Just to get metadata
var execution = self.manager.executeQuery(query);
execution.then(function (data) {
data = null;
});
return true;
};
self.SetParameters = function (parameters) {
self.parameter = ko.observable(parameters);
};
self.store = new breeze.MetadataStore(); // define metadataStore for all managers
self.manager = new breeze.EntityManager({
serviceName: self.serviceName,
metadataStore: self.store
});
} catch (error) {
var erroboj = { message: error.message };
self.Errors.push(erroboj);
}
}
try {
// Uncomment //debugger to debug this script. Use Visual Studio an IE to debug.
//debugger;
var viewModel = new SearchViewModel("Api/Vehicle", "Vehicles");
var parameter = {
Id: "AAB-1113",
Type: "CIF"
};
viewModel.SetParameters(parameter);
viewModel.Filter = function (Condition) {
"use strict";
var self = this;
var where = Condition.create("Type", "==", self.parameter.Type);
if (parameter.Id !== null) {
where = where.and("Id", "contains", self.parameter.Id);
}
return where;
};
ko.applyBindings(viewModel);
} catch (error) {
alert("Erro de codigo:".concat(error.message));
}
答案 0 :(得分:4)
最重要的问题:为什么你的querySucceeded
方法根本没有被调用?我假设你的queryFailed
也未被调用?应该击中一个或另一个。
您是否使用调试器验证了这两种方法都没有被调用?您确定服务器有任何查询结果吗?我将从网络流量日志中复制HTTP GET请求并在浏览器地址栏中重播它。只有在您确定服务器返回某些内容后,我才会继续处理查询结果。
注意:我刚看到问题陈述下方的完整ViewModel。
我在看到完整的VM之前写了我的回复,几乎重新开始。但我保留原来的答案,因为知道如何处理一个谜团很重要,而不仅仅是回答它。
问题几乎肯定与您的谓词有关。如果删除where(...)
子句,我敢打赌你会看到结果。我敢打赌,谓词设置的条件永远不会成立,因此你永远不会有任何结果显示出来。
在self.Find
内,您将谓词初始化为Breeze Predicate
构造函数。我认为你不想这样做。您可能想要创建一个新实例。
您似乎想要创建一个“身份条件” - 一个始终正确的条件。这对我来说似乎有点聪明。 NoFilterDefined
的效用和实现对我来说也是一个谜......但现在我已经远离了眼前的事情。
为什么不让self.Filter()
保持null
直到有实际的过滤条件?然后适当地构建您的查询,可能如下:
var query = breeze.EntityQuery.from(self.actionName); var predicate = self.Filter(); if (predicate) { query = query.where(predicate); }
您的 querySucceeded
似乎应该可行,但我更喜欢一些更改。例如,我不会逐个将查询结果项推送到KO observableArray中。为什么不直接使用查询结果数组?
function querySucceeded(data) { self.results(data.results); };
如果你担心在查询方法返回之前弄乱data.results
数组的东西(为什么?),你可以先复制它
self.results(data.results.slice());
小点:
我强烈建议将此类持久性问题从ViewModel移到辅助组件(例如dataservice
或datacontext
作为described here。
据我所知,您不需要任何fetchMetadata
业务。 Breeze在EntityManager的第一个查询中隐式获取元数据。您可以根据需要预先获取元数据(see MetadataStore.fetchMetadata
),但这里没有明显需要。
你的self.Find
方法是否应该向调用者返回承诺?
为什么您的querySucceeded
会返回true
?
您应该在执行查询之前清除self.results([])
中的self.Find
吗?我通常这样做。
为什么self.errors
中的queryFailed
是一个KO observableArray。您正在将错误消息推送到错误消息数组...您在方法开头清除的数组。为什么一个阵列?为什么不能观察到简单的KO?