请选择 进入手机版 | 继续访问电脑版
 找回密码
 立即注册

QQ登录

只需一步,快速开始

KevinChen 讲师达人认证 悬赏达人认证 SpreadJS 开发认证
论坛元老   /  发表于:2020-5-26 18:09  /   查看:1861  /  回复:0
在前一期中,我们讲了怎样在FlexGrid中保存JSON格式的数据,参考帖子:https://gcdn.grapecity.com.cn/showtopic-76344-1-1.html
实际上,想让JSON数据表现的跟简单数据一样的效果,没有那么简单,比如今天咱们要聊到的,这个数据如何实现复制粘贴?

如果我们尝试复制JSON格式的数据,会发现粘贴出来的仅仅是我们看到的值。
参考上一篇文章,复制操作拿到的是什么呢? 实际上,复制到剪贴板的是JSON对象toString后的结果,

所以我们可以让toString 返回一个JSON的stringify的字符串,如下代码所示:
  1. var countries = [];
  2.     countries[0] = {country:'US', continent:'North America'};
  3.     countries[1] = {country:'Germany', continent:'Europe'};
  4.     countries[2] = {country:'UK', continent:'Europe'};
  5.     countries[3] = {country:'Japan', continent:'Asia'};
  6.     countries[4] = {country:'Italy', continent:'Europe'};
  7.     countries[5] = {country:'Greece', continent:'Europe'};
  8.     var countryToString = function(){return JSON.stringify(this)};
  9.     countries.forEach(function(country){country.toString = countryToString;});
复制代码


仅仅修改这里后,单元格显示的内容就变成JSON字符串了,这怎么办?
FlexGrid有个formatItem的事件,可以按照我们自己想要的格式来显示单元格内容,如代码所示:
  1. theGrid.formatItem.addHandler(function (s, e) {
  2.         if (e.panel == s.cells) {
  3.             var col = s.columns[e.col];
  4.             if (col.binding == 'country') {
  5.                 var valueJson = s.getCellData(e.row, e.col);
  6.                 var value = JSON.parse(valueJson);
  7.                 if(value){
  8.                     e.cell.innerHTML = value.country;
  9.                 }
  10.             }
  11.         }
  12.     });
复制代码


这样就可以实现正常显示了。

最后,双击进入下拉菜单时,显示了json字符串可以用combobox的displayMemberPath属性来处理。参考代码:


  1.     new CustomGridEditor(theGrid, 'country', wjInput.ComboBox, {
  2.         itemsSource: countries,
  3.         displayMemberPath: 'country'
  4.     });
复制代码


本文涉及的完整的代码如下:

  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 JSON.stringify(this)};
  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.         displayMemberPath: 'country'
  285.     });
  286.     theGrid.formatItem.addHandler(function (s, e) {
  287.         if (e.panel == s.cells) {
  288.             var col = s.columns[e.col];
  289.             if (col.binding == 'country') {
  290.                 var valueJson = s.getCellData(e.row, e.col);
  291.                 var value = JSON.parse(valueJson);
  292.                 if(value){
  293.                     e.cell.innerHTML = value.country;
  294.                 }
  295.             }
  296.         }
  297.     });
  298. }
  299. //# sourceMappingURL=CustomGridEditor.js.map
复制代码


在这个示例上替换掉app.js即可看到效果:

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

0 个回复

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