web-dev-qa-db-fra.com

ExtJS 4: Modèles avec associations et magasins

Introduction

Je suis confronté à un problème de conception d'application avec la classe Ext.data.Model dans ExtJS. Je vais essayer de développer mes idées sur un scénario de magasin en ligne très commun ici, afin que vous puissiez me suivre. J'apprécierais vraiment tous les commentaires sur mes pensées et mes conclusions! 

Des modèles

Supposons que vous souhaitiez mapper le fait que "chaque client peut commander plusieurs produits}" à ExtJS. A partir des mots simples, on peut identifier ces trois modèles impliqués: Customer, Order et Product. Le Order dans ce cas est ce qui relie Customers et Products.

Les associations

J'ai trouvé qu'ExtJS vous permet en fait de spécifier cette relation (Customer)1-n(Order)1-n(Product) à l'aide des classes Ext.data.HasManyAssociation et Ext.data.BelongsToAssociation. Mais est-ce ce que l'on veut? Souhaitez-vous qu'un Product appartienne toujours à un Order? Et si vous voulez avoir une liste de Products sans aucune connexion avec Orders?

Magasins

C'est là que ça devient plus spécifique à ExtJS. Dans ExtJS, vous avez Ext.data.Stores pour stocker toutes vos données. Pour moi, un moyen naturel d’organiser mes données est d’avoir un Ext.data.Store pour chacun de mes modèles:

  1. CustomerStore
  2. OrderStore
  3. ProductStore

Pensez à avoir trois Ext.grid.Panels côte à côte; un pour chaque magasin. Lors de la sélection d'un client dans la première grille, ses commandes apparaissent automatiquement dans la deuxième grille. Lorsque vous sélectionnez une commande dans la deuxième grille, les produits associés apparaissent dans la troisième grille.

Est-ce que cela vous semble naturel? Si non, commentez s'il vous plaît!

Tout rassembler

Alors maintenant, nous avons trois choses que nous devons réunir:

  1. Les modèles et leurs
  2. Associations (hasMany, belongsTo) et le
  3. Données (Stores)

Est-il possible de définir une association uniquement d'un côté d'une relation modèle-modèle? Par exemple, puis-je spécifier un OrderhasManyProducts mais laisser de côté un ProductbelongsTo et un Order? Parce qu'un Product peut en réalité appartenir à plus d'un Order. Par conséquent, je précise que le modèle ProducthasManyOrders ci-dessous.

Voici les modèles dans ExtJS:

Client

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 */
});

Ordre

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 */
});

Produit

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'
});

Et voici les magasins:

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'
        }
    }
});

Voici un exemple (pas par moi) avec des entreprises et leurs produits http://superdit.com/2011/05/23/extjs-load-grid-from-another-grid/ . Il utilise deux modèles et deux magasins, mais aucune association n'est définie.

Merci d'avance

-Konrad

31
Konrad Kleine

Konrad. J'ai récemment eu affaire à Models+Associations+Stores. Ce n'était pas une expérience très agréable. Voici ce que j'ai appris:

Disons que nous avons Store1, Store2, Model1, Model2, Grid1, Grid2. Grid1 utilise Store1, Store1 utilise Model1 et de la même façon Grid2 utilise Store2, Store2 utilise Model2.

Jusqu'à présent, tout fonctionne, les données se chargent, etc.

Mais maintenant, nous voulons ajouter l’association hasMany à Model1. Ok, nous ajoutons à la configuration de Model1:

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

Après cela, vous pensez pouvoir renseigner Store2 avec les données de la variable itemclick de Grid1 en procédant comme suit:

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();
}

Vous vous attendez à ce que Grid2 soit rempli avec les données de la variable itemclick de Grid1. Mais rien ne se passe. Les demandes sont en train d'être postées, les réponses sont obtenues. Mais Grid2 n'est pas rempli de données.
Et après un certain temps, vous vous rendez compte que item_which_uses_model1.model2() IS NOT Store2.

lorsque Model2 "voit" qu'il est associé à Model1, il crée le magasin de Model1 qui n'est pas égal à Store2.

Ce n'est pas cool, car Grid2 utilise Store2.

En réalité, vous pouvez le pirater, par exemple en ajoutant à la configuration de Grid2:

store: new Model1().model2(),

mais que se passe-t-il si vous utilisez le modèle ExtJS mvc. Grid2 ne doit rien savoir de Model1.

Je ne recommande pas en utilisant associations dans des projets réels. Au moins maintenant. Utilisez plutôt l'approche qui est montrée dans votre exemple: Modèle + Magasin + Filtrage.

13
Molecular Man

Tout fonctionne bien dans ExtJS 4, il est difficile de réussir du premier coup. Eh bien, les premières fois.

Oui, vous pouvez éviter de spécifier l'association AppelsTo de l'enfant et l'utiliser quand même dans une relation à plusieurs.

Dans mon projet, nous avons des dizaines de modèles, dont beaucoup entretiennent des relations profondes, et cela fonctionne très bien. 

En ce qui concerne les relations plusieurs-beaucoup, vous devriez soit avoir

Client - <CustomerOrder> - Commande

Quel est trois modèles,

Ou vous pouvez "faire semblant" en faisant un tas de travail sur le serveur pour prétendre qu'un client a de nombreuses commandes. JSON imbriqué peut aider ici. 

9
Neil McGuigan

je suis entièrement d'accord avec Molecular Man. En lisant la documentation d'ExtJS, il est apparu plus évident que c'était un bon chemin lorsque vous utilisiez une structure d'ensembles d'arbres distribuée à différents magasins. Franchement, tout cela ne pourrait être vrai que si cette association avait de quelque manière que ce soit une référence de magasins pour faire des appels. Ce n'est pas le cas de ce que j'ai testé. Les associations modèles n'ont pas une telle relation. Le filtrage est le meilleur moyen de suivre la mise à jour séquentielle d'autres grilles dont les modèles dépendent d'autres.

2
flexnroses

Veuillez noter que votre hypothèse:

(Client) 1-n (Commande) 1-n (Produit)

est faux. Votre modèle actuel devrait être:

(Client) 1-n (Commande) n - n (Produit)

C'est pourquoi vous avez également rencontré des difficultés pour le modéliser avec hasMany-ownTo.

0
Jack