32 votes

ExtJS 4: Modèles avec associations et magasins

Introduction

Je suis face à une demande problème de conception de l' Ext.data.Model de la classe dans ExtJS. Je vais essayer de développer mes idées à un très commune de la boutique en ligne de scénario ici, donc vous pouvez me suivre. Je voudrais vraiment apprécier tous les commentaires sur mes pensées et mes conclusions!

Modèles

Supposons que vous souhaitez mapper le fait que "Chaque client peut commander plusieurs produits" pour ExtJS. À partir des mots nus, on peut identifier ces trois modèles concernés: Customer, Order, et Product. L' Order dans ce cas, est ce qui relie Customers et Products.

Les Associations

J'ai trouvé que ExtJS vous permet de spécifier ce (Customer)1-n(Order)1-n(Product) rapport à l'aide de l' Ext.data.HasManyAssociation et Ext.data.BelongsToAssociation les classes. Mais est-ce ce que l'on veut? Voudriez-vous qu'un Product appartient toujours à un Order? Que faire si vous voulez avoir une liste d' Products sans aucune connexion à Orders que ce soit?

Magasins

C'est là que c'est plus ExtJS spécifiques. Dans ExtJS vous avez Ext.data.Stores pour contenir toutes vos données. Pour moi un moyen naturel pour organiser mes données est d'avoir un Ext.data.Store pour chacun de mes modèles:

  1. CustomerStore
  2. OrderStore
  3. ProductStore

Envisager d'avoir un trois Ext.grid.Panels side-by-side, une pour chaque magasin. Lors de la sélection d'un client dans une grille, ses commandes s'affichent automatiquement dans la deuxième grille. Lors de la sélection d'une commande dans la deuxième grille, les produits associés figurent dans la troisième grille.

Est-ce son naturel pour vous? Si non, s'il vous plaît commentaire!

Réunissant tout

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

  1. Les modèles et leurs
  2. Associations (hasMany, belongsTo) et la
  3. De données (Stores)

Est-il possible de définir une association seulement d'un seul côté d'un Modèle-Modèle de relation? Par exemple, je peux préciser qu'un Order hasMany Products, mais laisser qu'un Product belongsTo un Order? Parce qu'un Product pouvez réellement appartenir à plus d'un Order. Donc je précise que l' Product modèle hasMany Orders ci-dessous.

Ici, ce sont les modèles en 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 */
});

Afin

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 les 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 il n'y a pas d'associations définir.

Je vous remercie à l'avance

-Konrad

15voto

Molecular Man Points 15187

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

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

Pour l'instant, tout fonctionne, les données en cours de chargement et ainsi de suite.

Mais maintenant, nous voulons ajouter hasMany association pour Model1. Ok, nous sommes en ajoutant à Model1 de la config:

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

Après cela, vous pensez que vous pouvez remplir Store2 avec des données sur Grid1 de l' itemclick en faisant quelque chose 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 attendez que Grid2 est rempli avec des données sur Grid1 de l' itemclick. Mais rien ne se passe. Actuellement les demandes sont affichées, les réponses sont obtenus. Mais Grid2 n'est pas rempli avec des données.
Et après quelques temps, vous se rendent compte qu' item_which_uses_model1.model2() N'EST Store2.

lorsque Model2 "voit" qu'il a association avec Model1 il crée Model1 propre magasin qui n'est pas égal à Store2.

C'est pas cool, parce que Grid2 est à l'aide de Store2.

Actuellement, vous pouvez pirater, par exemple, l'ajout de Grid2 de la config:

store: new Model1().model2(),

mais que faire si vous utilisez ExtJS modèle mvc. Grid2 doen pas de savoir quelque chose au sujet de Model1.

Je ne recommande pas d' utiliser associations dans le monde réel des projets. Au moins, maintenant. Au lieu d'utiliser l'approche qui est indiqué dans votre exemple: Modèle+Magasin+Filtrage.

9voto

Neil McGuigan Points 10123

Tout fonctionne bien en ExtJS 4, il est tout simplement difficile à obtenir dès la première fois. Ainsi, les premières fois.

Oui, vous pouvez éviter de spécifier l'association belongsTo de l'enfant, et de l'utiliser dans un A de Nombreuses relations.

Dans mon projet, nous avons des dizaines de modèles, de nombreux avec des relations profondes, et il fonctionne très bien.

Concernant les Nombreuses relations, vous devez avoir

Le Client< CustomerOrder >- Commande

Qui est de trois modèles,

Ou vous pouvez "faux" en faisant un tas de travail sur le serveur de prétendre qu'un client HasMany Commandes. Imbriquée json peut vous aider ici.

3voto

flexnroses Points 21

je suis entièrement d'accord avec Moléculaires de l'Homme. Par la lecture de la ExtJS documenation il est apparu plus comme une preuve que c'est une bonne voie lorsque vous faites usage d'un arbre de structure définie distribués aux différents magasins. Franchement, tout cela pourrait être vrai que si cette association avait en quelque sorte une référence de magasins pour faire des appels. Ce n'est pas le cas de ce que j'ai testé. Modèle associations n'ont pas cette relation. Le filtrage est la meilleure façon de maintenir de manière séquentielle la mise à jour d'autres grilles dont les modèles de dépendre des autres.

0voto

Jack Points 405

Veuillez noter que votre hypothèse:

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

est faux. Votre modèle réel devrait être:

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

C'est pourquoi vous avez également rencontré des difficultés à le modéliser avec hasMany-appartientTo

0voto

Snehal Masne Points 406

Règles pour les associations HasMany dans ExtJS

 • Always put your Proxies in your Models, not your Stores, unless you have a very good reason not to *
• Always require your child models if using them in hasMany relationships. ** 
• Always use foreignKey if you want to load the children at will
• Always use associationKey if you return the children in the same response as the parent
• You can use both foreignKey and associationKey if you like
• Always name your hasMany relationships
• Always use fully qualified model names in your hasMany relationship
• Consider giving the reader root a meaningful name (other than "data")
• The child model does not need a belongsTo relationship for the hasMany to work
 

Règles pour les associations HasOne et BelongsTo dans ExtJS

 • Put the proxy in the model, unless you have a very good reason not to [1]
• Always use fully qualified model name
• Always set the getterName
• Always set the setterName
• Always set the associationKey, if the foreign object is returned in the same response as this object
• Always set the foreignKey, if you want to load the foreign object at will
• Consider changing the instanceName to something shorter
• The getter behaves differently depending on whether the foreign object is loaded or not. If its loaded, the foreign object is returned. Otherwise, you need to pass in a callback to get it.
• You should set the name property if you plan to override this association.
• You do not need a belongsTo relationship for a hasMany to work
• Set the primaryKey property if the id field of the parent model is not "id"
• Sometimes you need to use uses or requires for the belongsTo association. Watch out for circular references though.
• Calling setter() function does not seem to set the instance. Set object.belongsToInstance = obj  if calling the setter().
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X