2010-10-20 18 views
4

J'ai un panneau EditorGrid fonctionnel, où deux colonnes ont des éditeurs ComboBox. Les deux ComboBox sont chargés à distance à partir de la base de données (countryStore et cityStore).ComboBox en cascade dans ExtJS EditorGridPanel

Je voudrais limiter le cityComboBox pour ne voir que les villes du pays sélectionné. J'ai besoin de recharger le cityStore avec un filtre de la base de données (il y a trop de villes pour filtrer localy). La valeur du filtre est la valeur countryComboBox. Il y a toujours une valeur dans countryComboBox, car j'ajoute un défaut = 1 lors de la création d'un nouvel enregistrement, donc ce n'est pas un problème.

Je ne sais pas quel écouteur serait approprié ici. J'ai besoin de saisir le moment où je double-clique sur la cellule de pays, avant que le countryComboBox apparaisse et filtre la zone de liste déroulante avant qu'il ne soit affiché (ou affiche un message d'attente pendant qu'il récupère des données).

Si ce n'est pas possible, puis-je ouvrir une fenêtre en double-cliquant sur une cellule, choisir une comboBox de villes filtrées, "confirmer" et entrer la valeur dans la cellule?

Répondre

5

Je l'ai finalement fait fonctionner. J'ai créé deux solutions - pour les recherches locales et distantes dans la grille. Finalement, j'ai décidé d'utiliser une recherche locale (je peux ajouter country_id à ma requête cities et filtrer dans ExtJS), mais il est possible de faire ça pour les recherches à distance - si quelqu'un en a besoin, je peux aussi préparer cette solution.

LOCAL SOLUTION

I a eu pour filtrer cityCombo en utilisant un événement beforeQuery, en utilisant l'identifiant de countryCombo dans la même rangée. Voici le code pour cityCombo:

var cityCombo = new Ext.form.ComboBox({ 
    triggerAction: 'all', 
    mode: 'local', 
    lastQuery: '', // to make sure the filter in the store is not cleared the first time the ComboBox trigger is used 
    store: cityDropdownStore, 
    displayField: 'city', 
    valueField: 'city_id', 
    listeners: { 
     beforeQuery: function(query) { 
      currentRowId = myGrid.getSelectionModel().getSelected().data.country_id; 
      this.store.clearFilter(); 
      this.store.filter({ property: 'country_id', value: currentRowId, exactMatch: true }); 
     } 
    } 
}); 

Comme vous pouvez le voir, lorsque l'cityCombo intérieur de la grille est le double cliquée, je reçois country_id dans la ligne actuelle et le filtre cityStore en utilisant cette valeur. Cela nécessite cityStore d'avoir ces domaines: id, country_id, city

Un problème reste: lorsque l'utilisateur change la countryCombo, le champ de la ville devrait changer/avertir l'utilisateur que ce n'est pas correct pour le pays actuel. La solution pour cela était compliquée ... comme vous le savez peut-être, vous ne pouvez pas obtenir une référence à parentGrid d'une comboBox (sinon vous pouvez simplement appeler countryCombo --> parentGrid --> currentRecord --> cityCombo --> change it).

J'ai essayé d'écouter l'événement rowchange sur la grille elle-même, mais si un utilisateur a cliqué sur une autre ligne directement après avoir changé countryCombo, il a changé la ville de la mauvaise rangée.

La solution était quelque peu avancée: j'ai dû copier les références de la ligne courante vers cityCombo à partir de l'événement beforeedit de la grille.Voici l'auditeur de la grille pour cela:

listeners: { 
    beforeedit: function(e) { 
     // reference to the currently clicked cell 
     var ed = e.grid.getColumnModel().getCellEditor(e.column, e.row);  
     if (ed && ed.field) { 
      // copy these references to the current editor (countryCombo in our case) 
      Ext.copyTo(ed.field, e, 'grid,record,field,row,column'); 
     } 
    } 
}, 

Maintenant, notre countryCombo a tous les neccessary d'information pour réinitialiser la ville quand il est changé. Voici l'ensemble du code countryCombo:

var countryCombo = new Ext.form.ComboBox({ 
    id: 'skupina_combo', 
    typeAhead: true, 
    triggerAction: 'all', 
    lazyRender: true, 
    mode: 'local', 
    store: countryDropdownStore, 
    displayField: 'country', 
    valueField: 'country_id', 
    listeners: { 
     change: function(t, n, o) { // t is the reference to the combo 
      // I have t.record available only because I copied it in the beforeEdit event from grid 
      t.record.set('city_id', '0'); 
     } 

    } 
}); 

cellulaires équarrisseurs n'a pas eu un problème avec moi filtrer leur magasin, donc je ne besoin d'un magasin à la fois le rendu et l'édition comboBox (de Citystore).

La solution à distance m'a demandé de créer deux magasins pour les villes - cityRendererStore et cityDropdownStore, qui interroge la base de données à chaque fois au lieu d'utiliser des filtres. Cette approche est nécessaire si vous avez trop de villes à filtrer localement. Je dois mentionner que je n'utilise pas vraiment les villes et les pays dans mon application, je viens de créer cet exemple pour simplifier les choses.

Je suis vraiment heureux du résultat final - il donne tous les avantages d'une grille avec des listes déroulantes conditionnelles habituellement disponibles uniquement dans les formulaires.

1

Je peux voir quelques options ici. Vous pouvez capturer l'événement update du magasin (lorsque l'enregistrement sous-jacent est mis à jour ou marqué comme sale) ou attraper l'événement select de countryComboBox. Ces deux éléments vous fourniront la valeur d'identifiant du pays sélectionné, que vous pourrez ensuite ajouter au code baseParams de votre cityComboBox pour le filtrage à distance.

+0

J'ai déjà essayé la première suggestion (événement 'update' du magasin), mais ça ne fonctionne pas - imaginez que je veux éditer une ville existante - Double-cliquez sur la liste déroulante de la ville. Le 'select' sur cityComboBox ne se déclenche que lorsque vous sélectionnez une valeur dans la liste déroulante - j'en ai besoin pour être filtré avant de sélectionner quoi que ce soit. Le paramètre 'select' de countryComboBox n'est pas activé lors de la modification de la ville d'un enregistrement existant (identique au problème' store store'). –

+0

Mais vous savez déjà ce que le combo de la ville devrait par défaut, puisque vous par défaut 'country = 1' droit? Un exemple de code dans votre question montrant votre configuration de grille et les gestionnaires d'événements serait utile :) – wes

+0

Eh bien, mon code ne ferait pas beaucoup de bien, car tout fonctionne aussi loin que les listes déroulantes dynamiques dans la grille modifiable vont. J'ai besoin du nouveau code. En ce qui concerne votre commentaire: oui, j'ai toujours pays = 1 (ou pays = valeur existante dans l'enregistrement), mais mon problème est comment filtrer le 'cityCombobBox' sur le champ' countryComboBox' de la ligne courante (que j'ai). –