2010-05-18 2 views
1

J'utilise EXTJS avec un éditeurgridpanel et j'essaie d'insérer une liste déroulante, remplie avec JsonStore. Voici un aperçu de mon code: LE MAGASIN:EXTJS 3.2.1 EditorGridPanel - ComboBox avec jsonstore

kmxgz.ordercmpappro.prototype.getCmpapproStore = function(my_url) { 
var myStore = new Ext.data.Store({ 
    proxy: new Ext.data.HttpProxy({ 
     url: my_url 
    , method: 'POST' 
    }) 
    , reader: new Ext.data.JsonReader({ 
     root: 'rows', 
     totalProperty: 'total', 
     id: 'list_cmpappro_id', 
     fields: [ 
        {name: 'list_cmpappro_id', mapping: 'list_cmpappro_id'} 
        , {name: 'list_cmpappro_name', mapping: 'list_cmpappro_name'} 
      ] 
     }) 
    , autoLoad: true 
    , id: 'cmpapproStore' 
    , listeners: { 
       load: function(store, records, options){ 
       //store is loaded, now you can work with it's records, etc. 
       console.info('store load, arguments:', arguments); 
       console.info('Store count = ', store.getCount()); 
     } 
     } 
}); 
return myStore; 
}; 

le COMBO:

kmxgz.ordercmpappro.prototype.getCmpapproCombo = function(my_store) { 
var myCombo = new Ext.form.ComboBox({ 
    typeAhead: true, 
    lazyRender:false, 
     forceSelection: true, 
    allowBlank: true, 
    editable: true, 
     selectOnFocus: true, 
     id: 'cmpapproCombo', 
    triggerAction: 'all', 
    fieldLabel: 'CMP Appro', 
    valueField: 'list_cmpappro_id', 
    displayField: 'list_cmpappro_name', 
    hiddenName: 'cmpappro_id', 
    valueNotFoundText: 'Value not found.', 
    mode: 'local', 
    store: my_store, 
    emptyText: 'Select a CMP Appro', 
     loadingText: 'Veuillez patienter ...',   
    listeners: { 

       // 'change' will be fired when the value has changed and the user exits the ComboBox via tab, click, etc. 
       // The 'newValue' and 'oldValue' params will be from the field specified in the 'valueField' config above. 
       change: function(combo, newValue, oldValue){ 
        console.log("Old Value: " + oldValue); 
        console.log("New Value: " + newValue); 
       }, 

       // 'select' will be fired as soon as an item in the ComboBox is selected with mouse, keyboard. 
       select: function(combo, record, index){ 
        console.log(record.data.name); 
        console.log(index); 
       } 
      } 

}); 
return myCombo; 
}; 

Le combobox est inséré dans un editorgridpanel. Il y a un renderer comme ceci:

Ext.util.Format.comboRenderer = function(combo){ 
    return function(value, metadata, record){ 
     alert(combo.store.getCount()); //<== always 0!! 
     var record = combo.findRecord(combo.valueField || combo.displayField, value); 
     return record ? record.get(combo.displayField) : combo.valueNotFoundText; 
    } 
}; 

Lorsque la grille est affichée la première fois, au lieu d'avoir le displayField, je: « Value not found. » Et j'ai l'alerte: 0 (alert (combo.store.getCount())) à partir du moteur de rendu. Mais je peux voir dans la console que les données ont été correctement chargées! Même si j'essaie de recharger le magasin depuis le moteur de rendu (combo.store.load();), j'ai toujours l'alerte (0)! Mais quand je sélectionne le combo pour changer la valeur, je peux voir les données et quand je change la valeur, je peux voir le displayFiel! Je ne comprends pas quel est le problème? Depuis maintenant plusieurs jours, j'ai déjà essayé toutes les solutions que j'ai trouvées ... mais toujours rien! Tout conseil est le bienvenu!

Yoong

Répondre

0

En fait, le problème semble être que la grille rend les valeurs de combobox AVANT le chargement des données du magasin. J'ai trouvé quelque chose here.

Mais quand j'ai appliqué le remplacement, toujours le même problème ... La question i: comment reporter le rendu de la combobox, en attendant le chargement du magasin?

+0

Je vais avoir le même problème. Toutes les solutions que vous avez trouvées? – dmackerman

0

Ceci est un problème courant. Si vous avez besoin d'une valeur de magasin à afficher dans la liste déroulante, gérez l'événement load du magasin et sélectionnez ensuite la valeur appropriée dans la liste déroulante. Vous ne devriez pas avoir besoin d'un enregistrement spécifique juste pour rendre le combo à l'avant.

+0

ok merci et désolé pour ma réponse tardive. J'essaierai quand j'aurai le temps et je te donnerai mes résultats à partager. –

0

Je vous recommande d'ajouter le champ requis dans le magasin de la liste déroulante, dans le magasin de la grille, et de changer le moteur de rendu pour utiliser ce champ. (Il ne doit pas être dans la base de données) et sur l'événement afteredit de la grille, récupérez cette valeur dans le magasin de la liste déroulante et copiez-la dans le magasin de la grille.

Cela donnerait de meilleures performances.

1

Le cœur du problème est que vous devez connecter un écouteur qui s'exécutera après le chargement de la grille. Cet écouteur convertira ensuite le contenu de la grille combinée au contenu displayField au lieu de valueField. Voici ma solution à ce problème.

Ext.ns("Ext.ux.renderer"); 
Ext.ux.renderer.ComboBoxRenderer = function(combo, grid) { 
    var getValue = function(value) { 
     var record = combo.findRecord(combo.valueField, value); 
     return record ? record.get(combo.displayField) : value; 
    }; 

    return function(value) { 
     var s = combo.store; 
     if (s.getCount() == 0 && grid) { 
      s.on({ 
       load: { 
        single: true, 
        fn: function() { 
         grid.getView().refresh() 
        } 
       } 
      }); 
      return value 
     } 
     return getValue(value) 
    } 
}; 

Vous pouvez utiliser ce moteur de rendu dans votre code comme suit:

{ 
      header: 'Header', 
      dataIndex: 'HeaderName', 
      autoWidth: true, 
      renderer: Ext.ux.renderer.ComboBoxRenderer(combo, grid), 
      editor: combo 
     }