2013-05-12 4 views
6

Mit ExtJS 4.2Zu verstehen, wie speichert Modelle/loade/instanziiert in ExtJS 4.2 MVC-Muster

referenziert werden habe ich viele Dokumente lesen, google, versuchen, Foren, wie Komponenten laden und wo zu verstehen, sie zu platzieren wie Geschäfte, Modelle , ect aber immer noch verwirrt.

Dies ist ein Beispiel, das ich

Applikationsbeschreibung

Hauptmenü mit Kontakten, Projekten, Menschen etc etc, App lädt zunächst zum Laufen zu bringen versuchen, ein statisches nicht datengesteuerte anzuzeigen, dann Klicks verwenden auf Kontakte, die ein Raster mit einer Liste von Kontakten anzeigt. Der Benutzer klickt dann auf eine Kontaktzeile und die Popup-Bearbeitungsansicht wird angezeigt.

In contaceditview wird der Kontakt in das Formular geladen, zusätzlich hat das Formular eine Combobox, die ContactTypes store lädt. Der ContactType sollte auf den Wert des Kontakttyps für diesen Kontaktdatensatz festgelegt werden.

Was ist der übliche Weg, dies zu tun, wenn man bedenkt, dass dies eine große Anwendung ist und ich nur die Daten laden will, wenn es notwendig ist, dh die Ansicht angezeigt wird.

Hier sind einige meiner Verwirrungen

1) Sie können alle von Ihnen Controller, Stores, Models, Views in der App Config definieren, aber dann ist alles egal geladen, welche Seite Sie suchen. Wenn Sie autoLoad: true in Ihren Stores haben, werden Aufrufe für alle Stores an die Datenbank gesendet, auch wenn Sie diese Ansicht nicht ansehen.

2) Wenn Sie einen Store oder ein Modell in der Stores oder Models-Eigenschaft in Ihrem Controller angeben, was genau macht das? Ist es einfach, dass Sie den Speicher einfach referenzieren, aber nicht wirklich erstellen oder erstellt er es oder setzt es nur Getter- und Setter-Funktionen für Bequemlichkeit. Beispiel, wenn ich einen Speicher in der Speichereigenschaft meines Controllers angeben und autoLoad true haben, werden alle Daten geladen, ohne dass etwas anderes getan werden muss. Aber was ich wirklich will ist, dass Laden nur lädt, wenn ich auf Kontakt klicke und die Listenansicht angezeigt wird. Also setze ich autoLoad: false und in meiner Listenfunktion erhalte ich manuell unter Verwendung this.getStore('Contacts'). Dies funktioniert gut, aber was ist der Zweck der Verwendung von Speichern und Modellen Array-Eigenschaft des Controllers. Ich sehe im Debugger, dass, wenn ich nicht die store/model-Eigenschaften verwende, eine get-Anfrage für diese js-Dateien gemacht wird.

Entschuldigung, ich weiß, das ist eine Menge, aber es ist sehr verwirrend für mich und habe mit ihm eine Weile gekämpft.

3) Schließlich habe ich das Kontaktraster nur geladen, wenn Sie auf die Schaltfläche Kontakte klicken, indem Sie autoLoad: false setzen und manuell laden. Wenn nun ein Benutzer auf "Bearbeiten" klickt, wird der Datensatz geladen, aber wie bekomme ich die Combobox zum Laden und wähle dann den richtigen Wert aus. Ich denke, ein Teil meines Problems ist zu verstehen, wie Ladenmodelle geladen und instanziiert werden. In meiner Combobox-Speichereigenschaft habe ich ContactType als den Speicher angegeben, aber ich bekomme Fehlerspeicher undefiniert, so dass entweder die js-Datei nicht geladen wird oder Speicher nicht instanziiert wird.

Hier ist mein Code so weit.

App-Code

Ext.Loader.setConfig({ 
    enabled: true, 
    paths: { 
     'Ext.ux': "lib/extux", 
     'Wakanda': "lib/extux/wakanda" 
    } 
}); 
Ext.application({ 
    name: 'SimplyFundraising', 
    autoCreateViewport: true, 

    requires: ['Ext.ux.Router', // Require the UX 
     'Wakanda.model'], 

    controllers: ['Contacts'], 
}); 

Kontakte-Controller

Ext.define('SimplyFundraising.controller.Contacts', { 
    extend: 'Ext.app.Controller', 


    views: ['contacts.List', 'contacts.Edit'], 
    init: function() { 
     this.control({ 
      'contactslist': { 
       itemdblclick: this.editContact, 
       removeitem: this.removeContact 
      }, 
      'contactslist > toolbar > button[action=create]': { 
       click: this.onCreateContact 
      }, 
      // 'contactsadd button[action=save]': { 
      // click: this.doCreateContact 
      // }, 
      'contactsedit button[action=save]': { 
       click: this.updateContact 
      } 
     }); 
    }, 
    list: function() { 

     var mystore = this.getStore('Contacts') 
     mystore.load(); 
// mystore.proxy.extraParams = { $expand: 'ContactType'}; 
//  var User = this.getContactModel(); 
//  User.load(258, { 
//   success: function (user) { 
//    console.log("Loaded user 258: " + user.get('lastName')); 
//   } 
//  }); 
    }, 
    editContact: function (grid, record) { 
     var view = Ext.widget('contactsedit'); 
     view.down('form').loadRecord(record); 
     this.addnew = false 
    }, 
    removeContact: function (Contact) { 
     Ext.Msg.confirm('Remove Contact ' + Contact.data.lastName, 'Are you sure?', function (button) { 
      if (button == 'yes') { 
       this.getContactsStore().remove(Contact); 
      } 
     }, this); 
    }, 
    onCreateContact: function() { 
     var view = Ext.widget('contactsedit'); 
     this.addnew = true 
    }, 
    // doCreateContact: function (button) { 
    // var win = button.up('window'), 
    // form = win.down('form'), 
    // values = form.getValues(), 
    // store = this.getContactsStore(); 
    // if (form.getForm().isValid()) { 
    // store.add(values); 
    // win.close(); 
    // } 
    // }, 
    updateContact: function (button) { 
     var win = button.up('window'), form = win.down('form'), record = form.getRecord(), values = form.getValues(), store = this.getContactsStore(); 
     if (form.getForm().isValid()) { 
      if (this.addnew == true) { 
       store.add(values); 
      } else { 
       record.set(values); 
      } 
      win.close(); 
     } 
    } 
}); 

Ansicht Kontakte Liste

Ext.define('SimplyFundraising.view.contacts.List', { 
    extend : 'Ext.grid.Panel', 
    xtype : 'contactslist', 
    title : 'All Contacts', 
    store : 'Contacts', 
    autoHeight: true, 
    autoScroll : true, 
    viewConfig : { 
     loadMask : true 
    }, 
    initComponent : function() { 
     this.tbar = [{ 
      text : 'Create Contact', 
      action : 'create' 
     }]; 
     this.columns = [{ 
      header : 'Id', 
      dataIndex : '__KEY', 
      width : 50 
     }, { 
      header : 'First Name', 
      dataIndex : 'firstName', 
      flex : 1 
     }, { 
      header : 'Middle Name', 
      dataIndex : 'middleName', 
      flex : 1 
     }, { 
      header : 'Last Name', 
      dataIndex : 'lastName', 
      flex : 1 
     }, 
     { 
      header : 'Type', 
      dataIndex : 'ContactType.name', 
      flex : 1 
     }]; 
     this.addEvents('removeitem'); 
     this.actions = { 
      removeitem : Ext.create('Ext.Action', { 
       text : 'Remove Contact', 
       handler : function() { 
        this.fireEvent('removeitem', this.getSelected()) 
       }, 
       scope : this 
      }) 
     }; 
     var contextMenu = Ext.create('Ext.menu.Menu', { 
      items : [this.actions.removeitem] 
     }); 
     this.on({ 
      itemcontextmenu : function(view, rec, node, index, e) { 
       e.stopEvent(); 
       contextMenu.showAt(e.getXY()); 
       return false; 
      } 
     }); 
     this.callParent(arguments); 
    }, 
    getSelected : function() { 
     var sm = this.getSelectionModel(); 
     var rs = sm.getSelection(); 
     if (rs.length) { 
      return rs[0]; 
     } 
     return null; 
    } 
}); 

Ansicht Kontakte bearbeiten

Ext.define('SimplyFundraising.view.contacts.Edit', { 
    extend: 'Ext.window.Window', 
    xtype: 'contactsedit', 
    title: 'Edit Contacts', 
    layout: 'fit', 
    autoShow: true, 
    initComponent: function() { 
     this.items = [ 
      { 
       xtype: 'form', 
       bodyStyle: { 
        background: 'none', 
        padding: '10px', 
        border: '0' 
       }, 
       items: [ 
        { 
         xtype: 'textfield', 
         name: 'firstName', 
         allowBlank: false, 
         fieldLabel: 'Name' 
        }, 
        { 
         xtype: 'textfield', 
         name: 'lastName', 
         allowBlank: false, 
         fieldLabel: 'Last Name' 
        }, 
        { 
         xtype: 'combobox', 
         fieldLabel: 'Contact Type', 
         name: 'contactType', 
         store: 'ContactTypes', 

         displayField: 'name', 
         typeAhead: true, 
         queryMode: 'local', 
         emptyText: 'Select a type...' 
        } 
       ] 
      } 
     ]; 
     this.buttons = [ 
      { 
       text: 'Save', 
       action: 'save' 
      }, 
      { 
       text: 'Cancel', 
       scope: this, 
       handler: this.close 
      } 
     ]; 
     this.callParent(arguments); 
    } 
}); 

Danke für jede Hilfe

+0

Haben Sie eine Antwort auf Ihre Frage gefunden? Ich stehe vor ähnlichen Problemen und bin verwirrt darüber, wie Stores in Ext.js MVC-Paradigma verwaltet werden. –

+0

Nein, leider nicht. Ich habe aufgehört, Extjs wegen der schlechten Dokumente und der nicht guten Unterstützung zu benutzen und verwende jetzt qooxdoo, es ist Extjs ähnlich und bis jetzt habe ich keine Probleme plus die Dokumentation und die Beispiele sind viel besser. Und es ist völlig kostenlos LGPL Lizenz, was bedeutet, dass Sie es in kommerziellen Produkten verwenden können. Schau es dir an http://qooxdoo.org/. Die Unterstützung ist Community-getrieben und ist ziemlich gut, besonders im Vergleich zu Sencha-Support. Und es wird aktiv entwickelt + aktive Blog-Updates. Nur das Problem, das ich hatte, war die erste Einrichtung, die nur die Build/Projekt-Erstellung zu verstehen. – dan

Antwort

2

Nicht verpassen mit ExtJs. Ich weiß, es könnte ein Schmerz ...

Für Ihr Problem, ich auf diese Weise gelöst:

Ich habe ein Raster, das Gemeinden Italien Liste. Ich möchte nach Land, Region und Provinz filtern, also lege ich drei Comboboxen auf einen angedockten Container. In der Steuerung habe ich:

 ,init : function (application) { 
     this.control({ 
      ,"#municipalitiesGrid": { afterrender: this.onMunicipalitiesGridAfterRender } 
     }); 
     } 
,onMunicipalitiesGridAfterRender: function(grid, opts) { 
    console.info('GVD.controller.Geo->onMunicipalitiesGridAfterRender'); 
    var store = grid.getStore(), 
     comboCountriesMunicipalities = this.getComboCountriesMunicipalities(), 
     storeCountries = comboCountriesMunicipalities.getStore(), 
     comboRegionsMunicipalities = this.getComboRegionsMunicipalities(), 
     storeRegions = comboRegionsMunicipalities.getStore(), 
     comboProvincesMunicipalities = this.getComboProvincesMunicipalities(), 
     storeProvinces = comboProvincesMunicipalities.getStore(); 

     store.clearFilter(true); 
     storeCountries.clearFilter(true); 
     storeRegions.clearFilter(true); 
     storeProvinces.clearFilter(true); 

     storeRegions.filter("idCountry", 114); // 114 = Italia 
     storeProvinces.filter("idRegion",8); // 8 = Emilia Romagna 
     store.filter("idProvince", 37);  // 37 = Bologna 

     storeCountries.load({ 
     scope: this, 
    callback: function(records, operation, success) { 
     storeRegions.load({ 
     scope: this, 
     callback: function(records, operation, success) { 
      storeProvinces.load({ 
      scope: this, 
     callback: function(records, operation, success) { 
      store.load({ 
      scope: this, 
      callback: function(records, operation, success) { 
       comboCountriesMunicipalities.setValue(114); // 114 = Italia 
       comboRegionsMunicipalities.setValue(8);  // 8 = Emilia Romagna 
       comboProvincesMunicipalities.setValue(37); // 37 = Bologna  
      } 
      }); 
     } 
      }); 
     } 
     }); 
     } 
     }); 
} 

in der Steuerung, natürlich, ich habe andere Zuhörer für Combobox des ‚Select‘ Ereignis, so kann ich filtern und Combo nachladen nach den ausgewählten Werten.

Nach MVC Rüttler, sind meine Geschäfte in etwa so:

Ext.define('GVD.store.Municipalities', { 
    extend: 'Ext.data.Store' 
    ,constructor: function(cfg) { 
     console.info('GVD.store.Municipalities->constructor'); 
     var me = this; 
     cfg = cfg || {}; 
     me.callParent([Ext.apply({ 
      autoLoad: false 
      ,autoSync: true 
      ,model: 'GVD.model.Municipalities' 
      ,pageSize: 20 
     }, cfg)]); 
    } 
}); 

Und Modelle ähnlich wie:

Ext.define('GVD.model.Municipalities', { 
    extend: 'Ext.data.Model', 

    fields: [ 
     { name: 'id',    type: 'int'   }, 
     { name: 'idIstat',  type: 'int'   }, 
     { name: 'idCountry',  type: 'int'   }, 
     { name: 'idRegion',  type: 'int'   }, 
     { name: 'idProvince',  type: 'int'   }, 
     { name: 'name',   type: 'string'  }, 
     { name: 'chief_town',  type: 'boolean'  }, 
     { name: 'altitude_zone', type: 'int'   }, 
     { name: 'altitude',  type: 'int'   }, 
     { name: 'coastal',  type: 'int'   }, 
     { name: 'mountain',  type: 'int'   }, 
     { name: 'surface',  type: 'double'  }, 
     { name: 'residents',  type: 'int'   }, 
     { name: 'icon',   type: 'string'  } 
    ] 
    ,proxy: { 
     api: { 
      create: 'Municipalities.create' 
      ,destroy: 'Municipalities.destroy' 
      ,read: 'Municipalities.read' 
      ,update: 'Municipalities.update' 
     } 
     ,reader: { 
      root: 'data' 
      ,totalProperty: 'totalCount' 
      ,type: 'json' 
     } 
     ,type: 'direct' 
    } 
}); 

Und in meinem Gitter auf diese Weise verwiesen:

Ext.define('GVD.view.system.geo.ListMunicipalities', { 
    autoScroll: true 
    ,constrain: true 
    ,dockedItems: [{ 
     xtype: 'topBar' 
    },{ 
     items: [{ 
       allowBlank: true 
       ,fieldLabel: 'Nazione' 
       ,flex: 1 
       ,id: 'comboCountriesMunicipalities' 
       ,labelAlign: 'right' 
       ,labelWidth: 50 
       ,listConfig: { 
        getInnerTpl: function() { 
         return '<img src="resources/images/countries/16/{icon}16.gif" align="left">&nbsp;&nbsp;{italianName}'; 
        } 
       } 
       ,store: Ext.create('GVD.store.Countries', {pageSize: 999}) 
       ,xtype: 'comboCountries'  
     },{ 
       allowBlank: true 
       ,fieldLabel: 'Regione' 
       ,flex: 1 
       ,id: 'comboRegionsMunicipalities' 
       ,labelAlign: 'right' 
       ,labelWidth: 50 
       ,listConfig: { 
        getInnerTpl: function() { 
         return '<img src="resources/images/regions/16/{icon}16.gif" align="left">&nbsp;&nbsp;{name}'; 
        } 
       } 
       ,store: Ext.create('GVD.store.Regions', {pageSize: 999}) 
       ,xtype: 'comboRegions' 
     },{ 
       allowBlank: true 
       ,fieldLabel: 'Provincia' 
       ,flex: 1 
       ,id: 'comboProvincesMunicipalities' 
       ,labelAlign: 'right' 
       ,labelWidth: 50 
       ,listConfig: { 
        getInnerTpl: function() { 
         return '<img src="resources/images/provinces/16/{icon}16.gif" align="left">&nbsp;&nbsp;{name}'; 
        } 
       } 
       ,store: Ext.create('GVD.store.Provinces', {pageSize: 999}) 
       ,xtype: 'comboProvinces'  
     }] 
     ,layout: 'hbox' 
     ,xtype: 'container' 
    }, { 
     dock: 'bottom' 
     ,itemId: 'municipalitiesPagingToolbar' 
     ,store: 'Municipalities' 
     ,xtype: 'pagingToolBar' 
    }] 
    ,extend: 'Ext.window.Window' 
    ,height: 400 
    ,icon: 'resources/images/GVD/municipalities16.png' 
    ,id: 'listMunicipalities' 
    ,items: [{ 
     columns: [{ 
      xtype: 'rownumberer' 
     },{ 
      align: 'right' 
      ,dataIndex: 'id' 
      ,format: '000' 
      ,renderer: function(value, metaData, record, rowIndex, colIndex, store, view) { 
       return '<img src="resources/images/municipalities/16/'+record.data.icon+'16.gif" align="left">&nbsp;&nbsp;'+record.data.id; 
      } 
      ,text: 'Id' 
      ,width: 70 
      ,xtype: 'numbercolumn' 
     },{ 
      align: 'right' 
      ,dataIndex: 'idIstat' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,format: '000000000' 
      ,text: 'Istat' 
      ,width: 80 
      ,xtype: 'numbercolumn'   
     },{ 
      dataIndex: 'name' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'string' } 
      ,flex: 1 
      ,text: 'Denominazione' 
      ,xtype: 'gridcolumn' 
     },{ 
      dataIndex: 'chief_town' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,text: 'Capoluogo' 
      ,width: 40 
      ,xtype: 'numbercolumn'  
      },{ 
      dataIndex: 'altitude_zone' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,format: '0' 
      ,text: 'Zona alt.' 
      ,width: 40 
      ,xtype: 'numbercolumn' 
     },{ 
      align: 'right' 
      ,dataIndex: 'altitude' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,format: '0000' 
      ,text: 'Altitudine' 
      ,width: 40 
      ,xtype: 'numbercolumn' 
     },{ 
      dataIndex: 'coastal' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,format: '0' 
      ,text: 'Costiero' 
      ,width: 40 
      ,xtype: 'numbercolumn' 
     },{ 
      dataIndex: 'mountain' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,format: '0' 
      ,text: 'Montano' 
      ,width: 40 
      ,xtype: 'numbercolumn' 
     },{ 
      align: 'right' 
      ,dataIndex: 'surface' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,format: '000,000.00' 
      ,text: 'Superficie' 
      ,xtype: 'numbercolumn' 
     },{ 
      align: 'right' 
      ,dataIndex: 'residents' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'numeric' } 
      ,format: '0,000,000' 
      ,text: 'residenti' 
      ,xtype: 'numbercolumn' 
     },{ 
      dataIndex: 'icon' 
      ,editor: { allowBlank: false, selectOnFocus: true } 
      ,filter: { type: 'string' } 
      ,flex: 1 
      ,text: 'Icona' 
      ,xtype: 'gridcolumn' 
     }] 
     ,columnLines: true 
     ,emptyText: '<font color="red"><b>Nessun comune in archivio</b></font>' 
     ,features: [ 
      Ext.create('GVD.ux.grid.FiltersFeature', { 
       encode: true, 
       ftype: 'filters', 
       local: false, 
       menuFilterText: 'Filtro' 
      }) 
     ]  
     ,id: 'municipalitiesGrid' 
     ,plugins: [ Ext.create('Ext.grid.plugin.RowEditing', { ptype: 'rowediting' }) ] 
     ,selModel: { selType: 'checkboxmodel', mode: 'MULTI' },store: 'Provinces' 
     ,store: 'Municipalities' 
     ,viewConfig: { 
      loadingText: 'Caricamento dati'  
      ,stripeRows: true 
      ,trackOver: true 
     } 
     ,xtype: 'grid' 
    }] 
    ,layout: { 
     align: 'stretch' 
     ,type: 'vbox' 
    } 
    ,margin: '0 0 2 0' 
    ,maximizable: true 
    ,minimizable: true 
    ,requires: [ 
     'GVD.ux.combo.Countries' 
     ,'GVD.ux.combo.Provinces' 
     ,'GVD.ux.combo.Regions' 
     ,'GVD.ux.PrintButton' 
     ,'GVD.ux.toolbar.BottomBar' 
     ,'GVD.ux.toolbar.PagingToolBar' 
     ,'GVD.ux.toolbar.TopBar' 
    ] 
    ,singleWindow: true 
    ,title: 'Elenco comuni' 
    ,tools: [ 
     { xtype: 'printButton', title: 'Elenco Comuni', tooltip: 'Stampa elenco' } 
     ,{ type: 'help', xtype: 'tool', tooltip: 'Guida sulla funzione' } 
    ] 
    ,width: 760 
}); 

Hoffnung Das kann helfen.

bye

+0

Ich schätze die Antwort und antworte, aber ich bin schon weitergezogen und bin bisher mit qooxdoo glücklich, hoffe das hilft jemand anderem! – dan