找回密码
 立即注册

QQ登录

只需一步,快速开始

KevinChen 讲师达人认证 悬赏达人认证 SpreadJS 开发认证
论坛元老   /  发表于:2020-5-26 17:34  /   查看:2554  /  回复:0
在FlexGrid中,单元格中是可以保存(引用)一个json对象的,比如数据源中,我们给对应字段设置一个json对象,可以成功与FlexGrid执行绑定。

但是默认情况下,绑定后的json无法正常显示,如图:


其实这是一个非常“基础”的问题,猜一下如果想让json对象显示出我们想要的内容,
应该怎么办?

对了,重写toString方法即可。

如下图所示:


但是,一旦我们更改了单元格的值,json对象就会被写入成普通的String字符串,怎么破?

OK,既然今天是【自定义编辑器系列】,那么肯定与自定义编辑器有关,如果将下拉菜单替换掉原始的input组件,
那么我们就可以在下拉菜单中回填给表格一个json对象就可以了,参考代码:

  1. import 'bootstrap.css';
  2. import '@grapecity/wijmo.styles/wijmo.css';
  3. import './styles.css';
  4. import * as wjGrid from '@grapecity/wijmo.grid';
  5. import * as wjInput from '@grapecity/wijmo.input';
  6. import * as wjCore from '@grapecity/wijmo';
  7. //
  8. // *** CustomGridEditor class (transpiled from TypeScript) ***
  9. //
  10. export class CustomGridEditor {
  11.     /**
  12.      * Initializes a new instance of a CustomGridEditor.
  13.      */
  14.     constructor(flex, binding, edtClass, options) {
  15.         // save references
  16.         this._grid = flex;
  17.         this._col = flex.columns.getColumn(binding);
  18.         // create editor
  19.         this._ctl = new edtClass(document.createElement('div'), options);
  20.         // connect grid events
  21.         flex.beginningEdit.addHandler(this._beginningEdit, this);
  22.         flex.sortingColumn.addHandler(() => {
  23.             this._commitRowEdits();
  24.         });
  25.         flex.scrollPositionChanged.addHandler(() => {
  26.             if (this._ctl.containsFocus()) {
  27.                 flex.focus();
  28.             }
  29.         });
  30.         flex.selectionChanging.addHandler((s, e) => {
  31.             if (e.row != s.selection.row) {
  32.                 this._commitRowEdits();
  33.             }
  34.         });
  35.         // connect editor events
  36.         this._ctl.addEventListener(this._ctl.hostElement, 'keydown', (e) => {
  37.             switch (e.keyCode) {
  38.                 case wjCore.Key.Tab:
  39.                 case wjCore.Key.Enter:
  40.                     e.preventDefault(); // TFS 255685
  41.                     this._closeEditor(true);
  42.                     this._grid.focus();
  43.                     // forward event to the grid so it will move the selection
  44.                     var evt = document.createEvent('HTMLEvents');
  45.                     evt.initEvent('keydown', true, true);
  46.                     'altKey,metaKey,ctrlKey,shiftKey,keyCode'.split(',').forEach((prop) => {
  47.                         evt[prop] = e[prop];
  48.                     });
  49.                     this._grid.hostElement.dispatchEvent(evt);
  50.                     break;
  51.                 case wjCore.Key.Escape:
  52.                     this._closeEditor(false);
  53.                     this._grid.focus();
  54.                     break;
  55.             }
  56.         });
  57.         // close the editor when it loses focus
  58.         this._ctl.lostFocus.addHandler(() => {
  59.             setTimeout(() => {
  60.                 if (!this._ctl.containsFocus()) {
  61.                     this._closeEditor(true); // apply edits and close editor
  62.                     this._grid.onLostFocus(); // commit item edits if the grid lost focus
  63.                 }
  64.             });
  65.         });
  66.         // commit edits when grid loses focus
  67.         this._grid.lostFocus.addHandler(() => {
  68.             setTimeout(() => {
  69.                 if (!this._grid.containsFocus() && !CustomGridEditor._isEditing) {
  70.                     this._commitRowEdits();
  71.                 }
  72.             });
  73.         });
  74.         // open drop-down on f4/alt-down
  75.         this._grid.addEventListener(this._grid.hostElement, 'keydown', (e) => {
  76.             // open drop-down on f4/alt-down
  77.             this._openDropDown = false;
  78.             if (e.keyCode == wjCore.Key.F4 ||
  79.                 (e.altKey && (e.keyCode == wjCore.Key.Down || e.keyCode == wjCore.Key.Up))) {
  80.                 var colIndex = this._grid.selection.col;
  81.                 if (colIndex > -1 && this._grid.columns[colIndex] == this._col) {
  82.                     this._openDropDown = true;
  83.                     this._grid.startEditing(true);
  84.                     e.preventDefault();
  85.                 }
  86.             }
  87.             // commit edits on Enter (in case we're at the last row, TFS 268944)
  88.             if (e.keyCode == wjCore.Key.Enter) {
  89.                 this._commitRowEdits();
  90.             }
  91.         }, true);
  92.         // close editor when user resizes the window
  93.         // REVIEW: hides editor when soft keyboard pops up (TFS 326875)
  94.         window.addEventListener('resize', () => {
  95.             if (this._ctl.containsFocus()) {
  96.                 this._closeEditor(true);
  97.                 this._grid.focus();
  98.             }
  99.         });
  100.     }
  101.     // gets an instance of the control being hosted by this grid editor
  102.     get control() {
  103.         return this._ctl;
  104.     }
  105.     // handle the grid's beginningEdit event by canceling the built-in editor,
  106.     // initializing the custom editor and giving it the focus.
  107.     _beginningEdit(grid, args) {
  108.         // check that this is our column
  109.         if (grid.columns[args.col] != this._col) {
  110.             return;
  111.         }
  112.         // check that this is not the Delete key
  113.         // (which is used to clear cells and should not be messed with)
  114.         var evt = args.data;
  115.         if (evt && evt.keyCode == wjCore.Key.Delete) {
  116.             return;
  117.         }
  118.         // cancel built-in editor
  119.         args.cancel = true;
  120.         // save cell being edited
  121.         this._rng = args.range;
  122.         CustomGridEditor._isEditing = true;
  123.         // initialize editor host
  124.         var rcCell = grid.getCellBoundingRect(args.row, args.col), rcBody = document.body.getBoundingClientRect(), ptOffset = new wjCore.Point(-rcBody.left, -rcBody.top), zIndex = (args.row < grid.frozenRows || args.col < grid.frozenColumns) ? '3' : '';
  125.         wjCore.setCss(this._ctl.hostElement, {
  126.             position: 'absolute',
  127.             left: rcCell.left - 1 + ptOffset.x,
  128.             top: rcCell.top - 1 + ptOffset.y,
  129.             width: rcCell.width + 1,
  130.             height: grid.rows[args.row].renderHeight + 1,
  131.             borderRadius: '0px',
  132.             zIndex: zIndex,
  133.         });
  134.         // initialize editor content
  135.         if (!wjCore.isUndefined(this._ctl['text'])) {
  136.             this._ctl['text'] = grid.getCellData(this._rng.row, this._rng.col, true);
  137.         }
  138.         else {
  139.             throw 'Can\'t set editor value/text...';
  140.         }
  141.         // start editing item
  142.         var ecv = grid.editableCollectionView, item = grid.rows[args.row].dataItem;
  143.         if (ecv && item && item != ecv.currentEditItem) {
  144.             setTimeout(function () {
  145.                 grid.onRowEditStarting(args);
  146.                 ecv.editItem(item);
  147.                 grid.onRowEditStarted(args);
  148.             }, 50); // wait for the grid to commit edits after losing focus
  149.         }
  150.         // activate editor
  151.         document.body.appendChild(this._ctl.hostElement);
  152.         this._ctl.focus();
  153.         setTimeout(() => {
  154.             // get the key that triggered the editor
  155.             var key = (evt && evt.charCode > 32)
  156.                 ? String.fromCharCode(evt.charCode)
  157.                 : null;
  158.             // get input element in the control
  159.             var input = this._ctl.hostElement.querySelector('input');
  160.             // send key to editor
  161.             if (input) {
  162.                 if (key) {
  163.                     input.value = key;
  164.                     wjCore.setSelectionRange(input, key.length, key.length);
  165.                     var evtInput = document.createEvent('HTMLEvents');
  166.                     evtInput.initEvent('input', true, false);
  167.                     input.dispatchEvent(evtInput);
  168.                 }
  169.                 else {
  170.                     input.select();
  171.                 }
  172.             }
  173.             // give the control focus
  174.             if (!input && !this._openDropDown) {
  175.                 this._ctl.focus();
  176.             }
  177.             // open drop-down on F4/alt-down
  178.             if (this._openDropDown && this._ctl instanceof wjInput.DropDown) {
  179.                 this._ctl.isDroppedDown = true;
  180.                 this._ctl.dropDown.focus();
  181.             }
  182.         }, 50);
  183.     }
  184.     // close the custom editor, optionally saving the edits back to the grid
  185.     _closeEditor(saveEdits) {
  186.         if (this._rng) {
  187.             var flexGrid = this._grid, ctl = this._ctl, host = ctl.hostElement;
  188.             // raise grid's cellEditEnding event
  189.             var e = new wjGrid.CellEditEndingEventArgs(flexGrid.cells, this._rng);
  190.             flexGrid.onCellEditEnding(e);
  191.             // save editor value into grid
  192.             if (saveEdits) {
  193.                 if(!wjCore.isUndefined(ctl['selectedItem'])){
  194.                     this._grid.setCellData(this._rng.row, this._rng.col, ctl['selectedItem']);
  195.                 }
  196.                 else if (!wjCore.isUndefined(ctl['value'])) {
  197.                     this._grid.setCellData(this._rng.row, this._rng.col, ctl['value']);
  198.                 }
  199.                 else if (!wjCore.isUndefined(ctl['text'])) {
  200.                     this._grid.setCellData(this._rng.row, this._rng.col, ctl['text']);
  201.                 }
  202.                 else {
  203.                     throw 'Can\'t get editor value/text...';
  204.                 }
  205.                 this._grid.invalidate();
  206.             }
  207.             // close editor and remove it from the DOM
  208.             if (ctl instanceof wjInput.DropDown) {
  209.                 ctl.isDroppedDown = false;
  210.             }
  211.             host.parentElement.removeChild(host);
  212.             console.log(flexGrid.getCellData(this._rng.row, this._rng.col));
  213.             this._rng = null;
  214.             CustomGridEditor._isEditing = false;
  215.             // raise grid's cellEditEnded event
  216.             flexGrid.onCellEditEnded(e);

  217.         }
  218.     }
  219.     // commit row edits, fire row edit end events (TFS 339615)
  220.     _commitRowEdits() {
  221.         var flexGrid = this._grid, ecv = flexGrid.editableCollectionView;
  222.         this._closeEditor(true);
  223.         if (ecv && ecv.currentEditItem) {
  224.             var e = new wjGrid.CellEditEndingEventArgs(flexGrid.cells, flexGrid.selection);
  225.             ecv.commitEdit();
  226.             setTimeout(() => {
  227.                 flexGrid.onRowEditEnding(e);
  228.                 flexGrid.onRowEditEnded(e);
  229.                 flexGrid.invalidate();
  230.             });
  231.         }
  232.     }
  233. }
  234. //
  235. document.readyState === 'complete' ? init() : window.onload = init;
  236. //
  237. function init() {
  238.     //
  239.     // create some random data
  240.     var countries = 'US,Germany,UK,Japan,Italy,Greece'.split(',');
  241.     countries[0] = {country:'US', continent:'North America'};
  242.     countries[1] = {country:'Germany', continent:'Europe'};
  243.     countries[2] = {country:'UK', continent:'Europe'};
  244.     countries[3] = {country:'Japan', continent:'Asia'};
  245.     countries[4] = {country:'Italy', continent:'Europe'};
  246.     countries[5] = {country:'Greece', continent:'Europe'};
  247.     var countryToString = function(){return this.country};
  248.     countries.forEach(function(country){country.toString = countryToString;});

  249.     var products = [
  250.         { id: 0, name: 'Widget', unitPrice: 23.43 },
  251.         { id: 1, name: 'Gadget', unitPrice: 12.33 },
  252.         { id: 2, name: 'Doohickey', unitPrice: 53.07 }
  253.     ];
  254.     var data = [];
  255.     var dt = new Date();
  256.     for (var i = 0; i < 100; i++) {
  257.         data.push({
  258.             id: i,
  259.             date: new Date(dt.getFullYear(), i % 12, 25, i % 24, i % 60, i % 60),
  260.             time: new Date(dt.getFullYear(), i % 12, 25, i % 24, i % 60, i % 60),
  261.             country: countries[Math.floor(Math.random() * countries.length)],
  262.             product: products[Math.floor(Math.random() * products.length)].name,
  263.             amount: Math.random() * 10000 - 5000,
  264.             discount: Math.random() / 4
  265.         });
  266.     }
  267.     //
  268.     // grid with custom editors
  269.     var theGrid = new wjGrid.FlexGrid('#theGrid', {
  270.         keyActionTab: 'CycleOut',
  271.         autoGenerateColumns: false,
  272.         itemsSource: data,
  273.         columns: [
  274.             { header: 'ID', binding: 'id', width: 40, isReadOnly: true },
  275.             { header: 'Date', binding: 'date', format: 'd' },
  276.             { header: 'Time', binding: 'time', format: 't' },
  277.             { header: 'Country', binding: 'country' },
  278.             { header: 'Product', binding: 'product' },
  279.             { header: 'Amount', binding: 'amount', format: 'n2' }
  280.         ],
  281.     });
  282.     new CustomGridEditor(theGrid, 'country', wjInput.ComboBox, {
  283.         itemsSource: countries
  284.     });
  285. }
  286. //# sourceMappingURL=CustomGridEditor.js.map
复制代码


以上代码在这个示例中可以看到效果(控制台中可以打印出当前修改的单元格json对象):

https://demo.grapecity.com.cn/wijmo/demos/Grid/CustomCells/CustomEditors/purejs

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

0 个回复

您需要登录后才可以回帖 登录 | 立即注册
返回顶部