web-dev-qa-db-ja.com

ExtJS 4:アソシエーションとストアを持つモデル

前書き

ExtJSのExt.data.Modelクラスに関するアプリケーション設計の問題に直面しています。ここで非常に一般的なオンラインストアシナリオに私のアイデアを発展させようとするので、私に従ってください。私の考えや結論についてコメントをいただければ幸いです!

モデル

すべての顧客が複数の製品を注文できる」という事実をExtJSにマッピングするとします。むき出しの言葉から、関連する3つのモデル、CustomerOrder、およびProductを特定できます。この場合のOrderは、CustomersとProductsを接続するものです。

協会

ExtJSでは、(Customer)1-n(Order)1-n(Product)クラスとExt.data.HasManyAssociationクラスを使用して、このExt.data.BelongsToAssociationリレーションを実際に指定できることがわかりました。しかし、これは望んでいることですか? Productは常にOrderに属しますか? Productsに接続せずにOrdersのリストを作成したい場合はどうしますか?

店舗

これは、ExtJS固有のものです。 ExtJSには、すべてのデータを保持するExt.data.Storesがあります。私にとって、データを整理する自然な方法は、各モデルにExt.data.Storeを持つことです:

  1. CustomerStore
  2. OrderStore
  3. ProductStore

3つのExt.grid.Panelsを並べて配置することを検討してください。店舗ごとに1つ。 1つのグリッドで顧客を選択すると、その注文は2番目のグリッドに自動的に表示されます。 2番目のグリッドで注文を選択すると、関連する製品が3番目のグリッドに表示されます。

この表現はあなたにとって自然ですか?そうでない場合は、コメントしてください!

すべてをまとめる

そのため、次の3つのことをまとめる必要があります。

  1. モデルとその
  2. 関連付け(hasManybelongsTo)および
  3. データ(Stores)

モデルとモデルの関係の片側からのみ関連付けを定義することは可能ですか?たとえば、OrderhasManyProductsと指定し、ProductbelongsToOrderProductは実際には複数のOrderに属することができるためです。したがって、以下のProduct model hasManyOrdersを指定します。

ExtJSのモデルは次のとおりです。

お客様

Ext.define('Customer', {
    extend   : 'Ext.data.Model',
    requires : [
        'Order',
    ],
    fields   : [
           {name : 'id',          type : 'int'},
           {name : 'lastname',    type : 'string'}
           {name : 'firstname',   type : 'string'}
    ],
    hasMany: 'Order' /* Generates a orders() method on every Customer instance */
});

注文

Ext.define('Order', {
    extend   : 'Ext.data.Model',
    fields   : [
            {name : 'id',          type : 'int'},
            {name : 'customer_id', type : 'int'}, /* refers to the customer that this order belongs to*/
            {name : 'date',        type : 'date'}
    ],
    belongsTo: 'Customer', /* Generates a getCustomer method on every Order instance */
    hasMany: 'Product' /* Generates a products() method on every Order instance */
});

製品

Ext.define('Product', {
    extend   : 'Ext.data.Model',
    fields   : [
            {name : 'id',          type : 'int'},
            {name : 'name',        type : 'string'},
            {name : 'description', type : 'string'},
            {name : 'price',       type : 'float'}
    ],
    /*
        I don't specify the relation to the "Order" model here
        because it simply doesn't belong here.

        Will it still work?
    */
    hasMany: 'Order'
});

そしてここに店があります:

CustomerStore

Ext.define('CustomerStore', {
    extend      : 'Ext.data.Store',
    storeId     : 'CustomerStore',
    model       : 'Customer',
    proxy   : {
        type   : 'ajax',
        url    : 'data/customers.json',
        reader : {
            type           : 'json',
            root           : 'items',
            totalProperty  : 'total'
        }
    }
});

OrderStore

Ext.define('OrderStore', {
    extend      : 'Ext.data.Store',
    storeId     : 'OrderStore',
    model       : 'Order',
    proxy   : {
        type   : 'ajax',
        url    : 'data/orders.json',
        reader : {
            type           : 'json',
            root           : 'items',
            totalProperty  : 'total'
        }
    }
});

ProductStore

Ext.define('ProductStore', {
    extend      : 'Ext.data.Store',
    storeId     : 'ProductStore',
    model       : 'Product',
    proxy   : {
        type   : 'ajax',
        url    : 'data/products.json',
        reader : {
            type           : 'json',
            root           : 'items',
            totalProperty  : 'total'
        }
    }
});

ここに、会社とその製品の例(私ではありません)があります http://superdit.com/2011/05/23/extjs-load-grid-from-another-grid/ 2つのモデルと2つのストアを使用しますが、定義する関連付けはありません。

前もって感謝します

-コンラッド

32
Konrad Kleine

コンラッド。最近、Models+Associations+Storesを扱うことに直面しました。これはあまり喜ばしい経験ではありませんでした。私が学んだことは次のとおりです。

Store1、Store2、Model1、Model2、Grid1、Grid2があるとします。 Grid1はStore1を使用し、Store1はModel1を使用し、同様にGrid2はStore2を使用し、Store2はModel2を使用します。

これまでのところ、すべてが機能しており、データがロードされています。

しかし今、Model1にhasMany関連付けを追加したいと思います。 OK、Model1の設定に追加しています:

hasMany: {model: 'Model2', name: 'model2'}

この後、次のようなことを行うことで、Grid1のitemclickのデータをStore2に追加できると思います。

Grid1.on('itemclick', function(view, item_which_uses_model1){
  //item_which_uses_model1.model2() supposed to return Model2's store
  item_which_uses_model1.model2().load();
}

Grid2には、Grid1のitemclickのデータが入力されることを期待しています。しかし、何も起こりません。実際に要求が投稿され、応答が得られます。ただし、Grid2にはデータが入力されていません。
そしてしばらくすると、item_which_uses_model1.model2()IS NOTStore2に気づきます。

model2がModel1との関連付けを「認識」すると、Store2とは異なるModel1自身のストアが作成されます。

Grid2はStore2を使用しているため、クールではありません。

実際には、例えばGrid2の設定に追加することでハックできます:

store: new Model1().model2(),

しかし、ExtJS mvcパターンを使用している場合はどうでしょう。 Grid2はModel1について何も知る必要はありません。

I 推奨しない現実のプロジェクトでassociationsを使用する。少なくとも今。代わりに、Model + Store + Filteringの例に示されているアプローチを使用してください。

15
Molecular Man

ExtJS 4ではすべて正常に動作しますが、初めて正しく動作するのは難しいです。まあ、最初の数回。

はい、子のbelongsToアソシエーションを指定することを避け、Has Many関係でそれを使用することができます。

私のプロジェクトでは、数十のモデルがあり、その多くは深い関係にあり、うまく機能しています。

多対多の関係については、

顧客-<CustomerOrder>-注文

これは3つのモデルです

または、顧客がHasMany Ordersを装ったふりをするためにサーバー上で多くの作業を行うことで、「偽造」することができます。ここでネストされたjsonが役立ちます。

9
Neil McGuigan

molecular Manに完全に同意します。 ExtJSのドキュメントを読むと、さまざまなストアに配布されているツリーセット構造を利用している場合、これが適切なルートであるという証拠としてより明らかになりました。率直に言って、この関連付けは、呼び出しを行うためのストアの参照が何らかの方法で関連付けられている場合にのみ当てはまります。私がテストしたものとは異なります。モデルの関連付けには、このような関係はありません。フィルタリングは、モデルが他のグリッドに依存している他のグリッドを連続的に更新するのに最適な方法です。

3
flexnroses

次のことに注意してください。

(顧客)1-n(注文)1-n(製品)

間違っている。実際のモデルは次のとおりです。

(顧客)1-n(注文)n-n(製品)

そのため、hasMany-belongsToを使用してモデル化することも困難でした。

0
Jack