8

顧客リストの各行に「削除」ボタンと「キャンセル」ボタンを配置したいと考えています。顧客が「未変更」の場合、「キャンセル」ボタンは無効になります。しかし、顧客が変更された状態 (「追加済み」、「変更済み」、「削除済み」) に移行したときに、「キャンセル」ボタンを有効にして、保存する前にユーザーが変更を元に戻すことができるようにしたいと考えています。

にサブスクライブすることで、これをほぼ行うことができますcustomer.entityAspect.propertyChanged。プロパティの変更は、 の潜在的な変更を示しEntityStateます。isChangedそのイベントをサブスクライブし、Customer エンティティに追加したオブザーバブルをハンドラーに更新させることができます。次に、「キャンセル」ボタンを有効にバインドして、準備完了isChangedです。

ただし、このイベントは、データ プロパティが変更propertyChangedされた場合にのみ発生します (例: . ユーザーが「削除」ボタンをクリックしても発生しません。データプロパティに触れない「削除」トリガー。顧客の を変更するだけです。customer.Name("New Co.");customer.entityAspect.setDelete();EntityState

(1) 顧客の変更が発生しないのはなぜですか? EntityState( 2) 「キャンセル」ボタンを制御できるようにpropertyChanged、変更をリッスンするにはどうすればよいですか?EntityState

PS: ノックアウトを使用しています。

PPS: この質問は、以前の SO の質問" entityAspect.setDeleted は、サブスクライブされた propertyChanged イベントを発生させません"に触発されました。

4

2 に答える 2

10

propertyChanged変更時に Breeze が発生しないことは正しいですEntityState。多分それはすべきです。検討いたします。

また、Breezeにはエンティティに別のイベント (イベントなし) がなくentityStateChanged、変更時に通知されますEntityState。私たちはそれを何度か検討しました。私たちはそれについて自分自身を話し続けています。

専用のentityStateChangedイベントよりも優れたパフォーマンスを発揮する、完全に優れたソリューションがあります。現時点では、自分でコーディングする必要があります。

秘訣はEntityManager、エンティティではなく、 をリッスンすることです。DocCode の「Teach Tests」サンプルには、このソリューションのバリエーションが 1 つあります。entityTest.jsモジュールで " can control custom ko entityState property via entityManager.entityChanged " を探します。

あなたの例に合うように微調整します。その本質は次のとおりです。

  1. entityManager.entityChangedイベントにサブスクライブします。それが発生し、その原因がエンティティのEntityState変更である場合、そのエンティティのisChangedブール KO オブザーバブルを更新します (そのプロパティが存在する場合)。

  2. isChangedこの方法で監視する必要があるエンティティ タイプにオブザーバブルを追加します。

ステップ 1 の例を次に示します: 状態の変化をリッスンする

// EntityState の変更を監視するハンドラでサブスクライブします
addEntityStateChangeTracking(マネージャー);

関数 addEntityStateChangeTracking(entityManager) {

    if (entityManager._entityStateChangeTrackingToken) { return; } // すでに追跡中

    // トークンを使用して変更追跡サブスクリプションを記憶します。
    // 将来、そのトークンで登録を解除する可能性があります
    entityManager._entityStateChangeTrackingToken =
        entityManager.entityChanged.subscribe(entityChanged);

    var entityStateChangeAction = Breeze.EntityAction.EntityStateChange;

    関数entityChanged(changeArgs) {            
        if (changeArgs.entityAction === entityStateChangeAction) {
            var エンティティ = changeArgs.entity;
            if (entity && entity.isChanged) { // エンティティにはオブザーバブルがあります
                var isUnchanged = entity.entityAspect.entityState.isUnchanged();
                entity.isChanged(!isUnchanged);
            }
        }
    }
}

ステップ 2 について話しましょう:isChangedオブザーバブルを型に追加します。あなたはそれに取り組んでいるようですが、どうすればよいかわかりません。おそらく、型に追加するのに最適な場所は型の初期化子であるため、エンティティが作成されたか、クエリによって具体化されたかに関係なく、プロパティがそこにあることを確認できます。次に例を示します。

var ストア = manager.metadataStore;

関数 customerInit(エンティティ) {
    var isUnchanged = entity.entityAspect.entityState.isUnchanged();
    entity.isChanged = ko.observable(!isUnchanged);
}

store.registerEntityTypeCtor('Customer', null, customerInit);

This all seems like a lot of work. It would be easier if Breeze raised the propertyChanged event when the EntityState changes. We'll give that more consideration ... there may be some good counter arguments. Meanwhile, I think what you see here is the best approach.

于 2013-01-12T21:10:25.767 に答える
0

特に hasChangesChanged イベントを使用すると、そよ風のエンティティ マネージャーを独自の内部にラップすることで、この課題を簡単に実行できる優れた柔軟性が得られることがわかりました。

var EntityManager = (function () {
    function EntityManager(breezeEntityManager) {
        this.breezeEntityManager = breezeEntityManager;
        this.hasChanges = ko.observable(breezeEntityManager.hasChanges());

        // Subscribe with handler watching for EntityState changes
        this.addEntityStateChangeTracking(breezeEntityManager, this);
    }

    EntityManager.prototype.addEntityStateChangeTracking = function (bem, em) {
        if (this.entityStateTrackingToken != null) return;
        this.entityStateTrackingToken = bem.hasChangesChanged.subscribe(function (changeArgs) {
            em.hasChanges(changeArgs.hasChanges);
        });
    };
    return EntityManager;
})();

次に、viewModels で EntityManager を公開します。

var ViewModel = (function (_super) {
    __extends(ViewModel, _super);
    function ViewModel(typeName) {
        _super.call(this);
        this.type = entities.getType(typeName);
    }

    ViewModel.prototype.loadEntity = function (id) {
        this.entityManager = new breeze.EntityManager("MyManager");;
    };
    return ViewModel;
})(ViewModelBase);
exports.ViewModel = ViewModel;

次に、ノックアウト UI で:

<button type="button" class="btn btn-info" data-i18n="common.save" data-bind="click: save, enable: entityManager.hasChanges">
于 2014-04-04T04:51:43.183 に答える