2013-01-12 4 views
8

お客様のリストの各行に「削除」ボタンと「キャンセル」ボタンを配置したいと思います。顧客が「変更されていない」場合、「キャンセル」ボタンは無効になります。しかし、顧客が変更された状態(「追加」、「変更済み」、「削除済み」)に移行すると、保存する前に変更を元に戻すことができるように「キャンセル」ボタンを有効にします。エンティティのEntityStateへの変更を検出するにはどうすればよいですか?

ほとんどこれはcustomer.entityAspect.propertyChangedに加入することで可能です。プロパティの変更は、EntityStateの潜在的な変更を通知します。私はそのイベントを購読することができ、私のハンドラが顧客のエンティティに追加したことを観測できるようにisChangedを更新させることができます。その後、私はisChangedに有効にする "キャンセル"ボタンをバインドして、私は行きたいです。

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

(1)なぜ私は「キャンセル」ボタンを制御することができ、顧客のEntityStateレイズpropertyChangedにない変化がないと、(2)どのように私はEntityStateへの変更のために聞くことができますか?

P .:私はノックアウトを使用しています。

P.P.S:この質問は以前のSOの質問"entityAspect.setDeleted doesn't fire the subscribed propertyChanged event"に触発されました。

答えて

10

EntityStateが変更された場合、BreezeがpropertyChangedを呼び出さないのは間違いありません。多分それはすべきです。我々はそれを考慮する。

NORは、ブリーズは、エンティティに別のイベント を持っていないん - 何entityStateChangedイベント - ときEntityStateの変更を通知するために。私たちはそれを何度か考えました。私たちはそれから自分たちのことを話し続けています。

専用のentityStateChangedイベントよりも優れたソリューションがあります。今すぐ自分でコードを作成する必要があります。

トリックは、エンティティではなくEntityManagerを聞くことです。 DocCode "Teach Tests"サンプルにこのソリューションの1つの変種があります。 entityTest.jsモジュール内の「entityManager.entityChanged」経由でカスタムko entityStateプロパティを制御できることを探します。

私はあなたの例に合わせてそれを微調整します。その本質は以下の通りです。

  1. entityManager.entityChangedイベントに登録してください。昇格時にが原因でエンティティのEntityStateが変更された場合、そのエンティティのisChangedブール型KO観測可能(そのプロパティが存在する場合)を更新します。

  2. このようにして監視する必要のあるエンティティタイプには、isChangedが追加されます。

ここでは、ステップ#1の例を示します状態をリッスンすることは

 
// subscribe with handler watching for EntityState changes 
addEntityStateChangeTracking(manager); 

function addEntityStateChangeTracking(entityManager) { 

    if (entityManager._entityStateChangeTrackingToken) { return; } // already tracking it 

    // remember the change tracking subscription with a token; 
    // might unsubscribe with that token in future 
    entityManager._entityStateChangeTrackingToken = 
     entityManager.entityChanged.subscribe(entityChanged); 

    var entityStateChangeAction = breeze.EntityAction.EntityStateChange; 

    function entityChanged(changeArgs) {    
     if (changeArgs.entityAction === entityStateChangeAction) { 
      var entity = changeArgs.entity; 
      if (entity && entity.isChanged) { // entity has the observable 
       var isUnchanged = entity.entityAspect.entityState.isUnchanged(); 
       entity.isChanged(!isUnchanged); 
      } 
     } 
    } 
} 

を変更するのは、ステップ#2についてお話しましょう:型に観測可能isChangedを追加します。あなたはそれに取り組んだようですが、私はどうしているのか分かりません。おそらく、型に追加するのに最適な場所はtype's initializerであるため、エンティティがクエリによって作成されたかマテリアライズされたかにかかわらず、プロパティがそこに存在することを確認できます。ここに例があります:

 
var store = manager.metadataStore; 

function customerInit(entity) { 
    var isUnchanged = entity.entityAspect.entityState.isUnchanged(); 
    entity.isChanged = ko.observable(!isUnchanged); 
} 

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

これはすべて多くの作業のようです。 EntityStateが変更されたときにBreezeがpropertyChangedイベントを発生させた方が簡単です。私たちはそれをもっと考慮するでしょう...いくつかの良い反論があるかもしれません。一方、私はあなたがここに見ているものが最良のアプローチだと思います。

+0

私たちは、この機能が進むかを確認するために見ることができるチケットはありますか?私のチームは、Breezeがこれを処理すると非常に便利だと思っていました。 –

+1

これをpropertyChangedEventに追加することをやめました。原則として、それはエンティティ・インフラストラクチャー・プロパティーではなく、ビジネス・オブジェクト・プロパティーの変更に関するものです。また、メモリリンクにつながる可能性の低いEntityManager.entityChangeイベントの使用をユーザーに推奨したいと考えています。そのネット:propertyChangedイベントの動作を変更する可能性は低いです。 – Ward

+0

この回答に感謝します。 –

0

私たち自身の中にbreeze entity managerをラップすると、特に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を公開します。あなたのノックアウトUIで次に

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; 

<button type="button" class="btn btn-info" data-i18n="common.save" data-bind="click: save, enable: entityManager.hasChanges">