简体   繁体   中英

How to display a property in a combobox within a grid with CellEditing plugin and save a complete JSON in ExtJS 4.2

I am trying to display a property from a JSON received from a server in a combobox within a grid with cell editing. When the user selects an option I want to display the same property, but when the user saves the grid, I want the complete JSON to be sent to the server (not just the display value nor the id field).

This is what I have so far (available here http://jsfiddle.net/apater39/do0xg4r1/ ):

Ext.define('NS.model.State', {
  extend: 'Ext.data.Model',
  fields: [{
    name: 'id',
    type: 'int'
  }, {
    name: 'name',
    type: 'string'
  }]
});
Ext.define('NS.store.State', {
  extend: 'Ext.data.Store',
  model: 'NS.model.State',
  data: [{
    "id": 1,
    "name": "Alabama"
  }, {
    "id": 2,
    "name": "Alaska"
  }, {
    "id": 3,
    "name": "Arizona"
  }]
});

Ext.define('NS.model.Person', {
  extend: 'Ext.data.Model',
  fields: [{
    name: 'id',
    type: 'int'
  }, {
    name: 'firstName',
    type: 'string'
  }, {
    name: 'state',
    type: 'NS.model.State'
  }]
});

Ext.define('NS.store.Grid', {
  extend: 'Ext.data.Store',
  model: 'NS.model.Person',
  data: {
    'items': [{
      'id': 1,
      "firstName": "Lisa",
      "state": null
    }, {
      'id': 2,
      "firstName": "Bart",
      "state": null
    }, {
      'id': 3,
      "firstName": "Homer",
      "state": null
    }, {
      'id': 4,
      "firstName": "Marge",
      "state": null
    }]
  },
  proxy: {
    type: 'memory',
    reader: {
      type: 'json',
      root: 'items'
    }
  }
});

Ext.create('Ext.grid.Panel', {
  title: 'Simpsons',
  store: Ext.create('NS.store.Grid'),
  columns: [{
    header: 'First Name',
    dataIndex: 'firstName',
    flex: 1,
    editor: 'textfield'
  }, {
    header: 'State',
    dataIndex: 'state',
    flex: 1,
    editor: {
      xtype: 'combobox',
      store: Ext.create('NS.store.State'),
      queryMode: 'local',
      displayField: 'name',
      valueField: 'id'
    }
  }],
  selType: 'cellmodel',
  plugins: [{
    ptype: 'cellediting',
    clicksToEdit: 2
  }],
  height: 150,
  width: 200,
  renderTo: Ext.getBody()
});

If I use valueField 'id' then when the user chooses an option from the combobox the id is displayed (instead of the displayField).

The JSON that I would like to be sent is this:

{
  "id": 1,
  "firstName": "Lisa",
  "state": 
   {
     "id": 1,
     "name": "Alabama"
   }
}

Thanks for the help.

UPDATE:

Based on the suggestion of Jorge Ramon, I arrived at a solution (see http://jsfiddle.net/apater39/8opsqg5s/ ). The important thing is to to listen to the edit event of cellediting pluging, and then find the selected record of the combo and set the corresponding property.

var gridPanel = Ext.create('Ext.grid.Panel', {
  title: 'Simpsons',
  store: gridStore,
  columns: [{
    header: 'First Name',
    dataIndex: 'firstName',
    flex: 1,
    editor: 'textfield'
  }, {
    header: 'State',
    dataIndex: 'state',
    flex: 1,
    editor: {
      xtype: 'combobox',
      store: Ext.create('NS.store.State'),
      displayField: 'name',
      valueField: 'name',
      editable: false,
      queryMode: 'local',
      forceSelection: true,
      triggerAction: 'all',
      selectOnFocus: true,
      allowBlank: false
    },
    renderer: function(value) {
      return value.name;
    }
  }],
  selType: 'cellmodel',
  plugins: [{
    ptype: 'cellediting',
    clicksToEdit: 2,
    listeners: {
      edit: function(editor, ctx, eOpts) {
        var vendorColIdx = 1;
        if (vendorColIdx === ctx.colIdx) {
          var combo = ctx.grid.columns[vendorColIdx].getEditor(ctx.record);
          var vendorRecord = combo.findRecord('name', ctx.record.get('state'));
          ctx.record.set('state', vendorRecord.data);
        }
        ctx.grid.getStore().sync();
      }
    }
  }],
  height: 250,
  width: 200,
  renderTo: Ext.getBody()
});

The JSON sent becomes:

{"id":1,"firstName":"Lisa","state":{"id":2,"name":"Alaska"}}

You will need to change several stuff in your code to achieve want you want to do...

First is that your are trying to work with association (Person contains a State) but you are not declaring the association. To declare your association correctly, I suggest to read this : https://stackoverflow.com/a/16492938/3494608 And also deeply suggest to read this : http://extjs-tutorials.blogspot.fr/2012/05/extjs-hasmany-relationships-rules.html

Afterward, you will need to see how to correctly set your association because your combobox here only set a value (the id of the model corresponding to the select state) and not the record itself.

And then, you will see how to send the complete model with association. I did not did it myself within Ext4.2 but you'll find some lecture in google (Key words: extjs save nested model). Found this first : https://www.sencha.com/forum/showthread.php?274778-Add-new-record-of-Model-that-contains-nested-Model

I don't have a "all-in-one" solution because working with association is unfortunately a though work with ExtJs (less with ExtJs 5+ but still...)

Good luck!

You want to have the combo editor set like this example:

editor: {
    xtype: 'combobox',
    store: 'Vendors',
    displayField: 'name',
    valueField: 'name',
    editable: false,
    queryMode: 'remote',
    forceSelection: true,
    triggerAction: 'all',
    selectOnFocus: true,
    allowBlank: false
}

Then, use the celleditor plugin:

plugins: {
   ptype: 'cellediting',
   clicksToEdit: 1,
   listeners: {
       edit: 'onGridEditorEdit'
   }
}

And handle the plugin's edit event:

onGridEditorEdit: function (editor, ctx, eOpts) {
    var vendorColIdx = 2;
    if (vendorColIdx === ctx.colIdx + 1) {
        var combo = ctx.grid.columns[vendorColIdx].getEditor(ctx.record);
        var vendorRecord = combo.findRecord('name', ctx.record.get('vendorName'));
        ctx.record.set('vendorId', vendorRecord.get('id'));
    }
    ctx.grid.getStore().sync();  // Force a post with the updated data.     
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM