0

我被困在这一点上,无法继续。

我正在以这种方式为搜索表单创建 ViewModel:

var viewModel = new SearchViewModel("Api/Vehicle", "Vehicles");
ko.applyBindings(viewModel);

稍后当用户单击查找按钮时,它会触发查找方法(此处简化):

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 的数据永远不会更新触发数据绑定。

我做错了什么?


这是视图模型。有点不完整和模糊。我想我没有正确理解微风查询的承诺:

/*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));
}
4

1 回答 1

4

最重要的问题:为什么你的querySucceeded方法根本没有被调用?我假设你的queryFailed也没有被调用?一个或另一个应该被击中。

您是否使用调试器验证过这两种方法都没有被调用?您确定服务器有任何查询结果吗?我将从网络流量日志中复制 HTTP GET 请求并在浏览器地址栏中重放它。只有在您确定服务器正在返回某些内容之后,我才会继续处理查询结果。


注意:我刚刚在您的问题陈述下方看到了完整的 ViewModel。

我在看到完整的虚拟机之前写了回复,几乎重新开始。但是我保留了我原来的答案,因为知道如何解决一个谜很重要,而不仅仅是回答它。

几乎可以肯定,问题出在您的谓词上。where(...)如果您删除该子句,我敢打赌您会看到结果。我敢打赌,谓词设置的条件永远不会为真,因此您永远不会显示任何结果。

在内部self.Find,您将谓词初始化为 BreezePredicate构造函数。我不认为你想这样做。您可能想要创建一个新实例。

您似乎想要创建一个“身份条件” - 一个始终为真的条件。这对我来说似乎有点聪明。的实用性和实现对NoFilterDefined我来说也是一个谜……但现在我离手头的事情还很远。

为什么不让 letself.Filter()保持null直到有实际的过滤条件?然后适当地构建您的查询,可能如下所示:

var 查询 = 微风.EntityQuery.from(self.actionName);
var predicate = self.Filter();
if (predicate) { query = query.where(predicate); }

查看此谓词介绍


尽管我希望进行一些更改,但您querySucceeded似乎应该可以使用。例如,我不会将查询结果项一一推送到 KO observableArray 中。为什么不只使用查询结果数组?

函数查询成功(数据){
    self.results(data.results);
};

如果您担心data.results在查询方法返回之前会弄乱数组(为什么?),您可以先复制它

self.results(data.results.slice());

小分:

  • 我强烈建议将诸如此类的持久性问题从 ViewModel 中移出,并将其移至辅助组件中,例如此处描述dataservice的 a或。datacontext

  • fetchMetadata据我所知,你不需要任何业务。Breeze 在 EntityManager 的第一次查询时隐式获取元数据。如有必要,您可以预取元数据(请参阅MetadataStore.fetchMetadata),但这里没有明显的需要。

  • 您的self.Find方法应该将承诺返回给调用者吗?

  • 为什么你的querySucceeded回报true

  • self.results([])您应该在self.Find 执行查询之前清除吗?我通常会。

  • 为什么self.errorsqueryFailedKO observableArray 中。您正在将错误消息推送到错误消息数组中……您在方法开始时清除的数组。为什么是数组?为什么不是一个简单的 KO observable?

于 2012-11-27T18:26:17.077 回答