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 が表示されました。

完全な VM を見る前に返信を書き、ほとんど最初からやり直しました。しかし、ミステリーに答えるだけでなく、ミステリーに取り組む方法を知ることが重要なので、元の答えを保持しています。

問題はほぼ確実に述語にあります。where(...)句を削除すると、結果が表示されるに違いありません。私の賭けは、述語が決して真ではない条件を設定するため、表示する結果がまったくないということです。

内部self.Findでは、述語を BreezePredicateコンストラクターに初期化します。私はあなたがそれをしたいとは思わない。おそらく、新しいインスタンスを作成したいと思うでしょう。

あなたは「同一性条件」を作成したいと考えているようです - 常に真である条件です。これは私には少し賢いようです。の有用性と実装NoFilterDefinedも私には謎です...しかし、今、私は目前の問題から遠く離れています。

self.Filter()実際のフィルター条件が整うnullまで放置しないのはなぜですか? 次に、おそらく次のように、クエリを適切に作成します。

var query = Breeze.EntityQuery.from(self.actionName);
var 述語 = self.Filter();
if (述語) { クエリ = query.where(述語); }

predicate のこの紹介をチェックしてください。


いくつquerySucceededかの変更を希望しますが、動作するはずです。たとえば、クエリ結果アイテムを 1 つずつ KO observableArray にプッシュすることはしません。クエリ結果配列を使用しないのはなぜですか?

関数 querySucceeded(データ) {
    self.results(data.results);
};

クエリ メソッドが返される前に配列をいじる何かが心配な場合data.results(なぜですか?)、最初にそれをコピーできます。

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

より少ないポイント:

  • dataserviceこれらの永続化の問題を ViewModel からorなどのヘルパー コンポーネントに移動することを強くお勧めdatacontextます

  • fetchMetadata私が知る限り、そのビジネスは必要ありません。Breeze は、EntityManager の最初のクエリで暗黙的にメタデータを取得します。必要に応じてメタデータをプリフェッチできますが ( 「 」を参照MetadataStore.fetchMetadata)、ここでは明らかな必要性はありません。

  • あなたのself.Findメソッドは約束を呼び出し元に返す必要がありますか?

  • なぜquerySucceeded戻ってくるのtrueですか?

  • クエリを実行する前にクリアする必要がself.results([])ありますか? self.Find私は通常そうします。

  • なぜKO observableArrayself.errorsにあるのか。queryFailedエラーメッセージをエラーメッセージの配列にプッシュしています...メソッドの開始時にクリアした配列です。なぜ配列?単純な KO オブザーバブルではないのはなぜですか?

于 2012-11-27T18:26:17.077 に答える