2

これまでのところ、非常にうまく機能しているシングル ページ アプリケーションがありますが、理解できない問題に遭遇しました。私はそよ風を使用して、テーブルに表示されるプロジェクトのリストを作成しています。実際に必要なものよりもはるかに多くの情報があるため、データの投影を行っています。エンティティに計算されたノックアウトを追加したい。これを達成するために、私は登録し、エンティティコンストラクターをそのように...

metadataStore.registerEntityTypeCtor(entityNames.project, function () { this.isPartial = false; }, initializeProject);

initializeProject 関数は、プロジェクト内の値の一部を使用して、計算対象の値を決定します。たとえば、Project.Type == "P" の場合、rowClass は = "Red" にする必要があります。

私が抱えている問題は、たまたまキーである ProjNum を除いて、Project のすべてのプロパティが null であることです。問題は、他のタイプの他の初期化子を登録していて、正常に機能するため、投影を行っているためだと思います。これを機能させる方法はありますか?

編集:明確にするために、もう少し詳細を追加すると思いました。Chrome で JavaScript デバッガーを使用してプロパティに問い合わせると、すべてのプロパティの _latestValue が null になります。設定される唯一のプロパティは、エンティティ キーでもある ProjNum です。

EDIT2:これは、投影を行うクライアント側のコードです

var getProjectPartials = function (projectObservable, username, forceRemote) {
    var p1 = new breeze.Predicate("ProjManager", "==", username);
    var p2 = new breeze.Predicate("ApprovalStatus", "!=", "X");
    var p3 = new breeze.Predicate("ApprovalStatus", "!=", "C");

    var select = 'ProjNum,Title,Type,ApprovalStatus,CurrentStep,StartDate,ProjTargetDate,CurTargDate';

    var isQaUser = cookies.getCookie("IsQaUser");

    if (isQaUser == "True") {
        p1 = new breeze.Predicate("QAManager", "==", username);
        select = select + ',QAManager';
    } else {
        select = select + ',ProjManager';
    }

    var query = entityQuery
        .from('Projects')
        .where(p1.and(p2).and(p3))
        .select(select);

    if (!forceRemote) {
        var p = getLocal(query);
        if (p.length > 1) {
            projectObservable(p);
            return Q.resolve();
        }
    }

    return manager.executeQuery(query).then(querySucceeded).fail(queryFailed);

    function querySucceeded(data) {
        var list = partialMapper.mapDtosToEntities(
            manager,
            data.results,
            model.entityNames.project,
            'ProjNum'
        );
        if (projectObservable) {
            projectObservable(list);
        }
        log('Retrieved projects using breeze', data, true);
    }
};

および partialMapper.mapDtosToEntities 関数のコード。

var defaultExtension = { isPartial: true };

function mapDtosToEntities(manager,dtos,entityName,keyName,extendWith) {
    return dtos.map(dtoToEntityMapper);

    function dtoToEntityMapper(dto) {
        var keyValue = dto[keyName];
        var entity = manager.getEntityByKey(entityName, keyValue);
        if (!entity) {
            extendWith = $.extend({}, extendWith || defaultExtension);
            extendWith[keyName] = keyValue;
            entity = manager.createEntity(entityName, extendWith);
        }
        mapToEntity(entity, dto);
        entity.entityAspect.setUnchanged();
        return entity;
    }

    function mapToEntity(entity, dto) {
        for (var prop in dto) {
            if (dto.hasOwnProperty(prop)) {
                entity[prop](dto[prop]);
            }
        }
        return entity;
    }
}

EDIT3:それは私の間違いだったようです。initializeProject を詳しく調べたところ、エラーが見つかりました。以下は、修正前の関数の外観です。

function initializeProject(project) {
    project.rowClass = ko.computed(function() {
        if (project.Type == "R") {
            return "project-list-item info";
        } else if (project.Type == "P") {
            return "project-list-item error";
        }
        return "project-list-item";
    });
}

問題は project.Type にありました。これは監視可能であるため、project.Type() を使用する必要がありました。このプロジェクトを開始して以来、私が何度も犯してきた愚かな間違いです。

EDIT4: initializeProject の内部では、機能している部分と機能していない部分があります。project.ProjTargetDate() にアクセスしようとすると、project.StartDate() と同じように null が返されます。Null 値が原因で、これらの日付を使用してプロジェクトがいつ遅れているかを判断しているときに、モーメント ライブラリからエラーがスローされます。クライアントクエリからの選択と部分エンティティマッパーへの呼び出しを削除しようとしましたが、それを行うとすべて正常に機能しました。

4

1 に答える 1

2

あなたは近づいているようです。あなたのinitializeProjectメソッドにいくつかのガード句が役立つと思います.Knockoutを使用する場合、常に括弧の問題と戦っています.

ところで、バインドの問題を診断するには、Chrome 用のKnockout Context Debuggerプラグインを強くお勧めします。

toType() を試してください

John のコースのコードに従って、DTO マッピングに懸命に取り組んでいます。それ以来、射影データをエンティティに取得する新しい方法がtoType(...)あります。次のようにクエリの最後に追加します。

var クエリ = entityQuery
        .from('プロジェクト')
        .where(p1.and(p2).and(p3))
        .select(選択)
        .toType('プロジェクト') ; // プロジェクトにキャスト

すべてが解決するわけではありませんが、dto マッピングを廃止できる場合があります。

サーバー上の DTO を検討する

これを最初に指摘しておくべきでした。このデータを常にサイズに切り詰めている場合は、クライアントに合わせてクライアント向けモデルを定義してみませんか。適切な形状の DTO クラスを作成し、サーバー上でそれらに投影してから、データをネットワーク経由で送信します。

また、これらの DTO に一致するメタデータを作成しProjectて、クライアントがそこにあるはずのプロパティを正確に持つようにすることもできます。

私は今これについて書いています。1週間ほどでページが完成するはずです。

于 2013-05-08T17:23:38.920 に答える