Popups: Delete Rows with Ctrl+Delete

(Or Fn+Delete on Mac keyboards)

You can handle keyboard events in the FlexGrid by adding HTML event listeners to the grid's hostElement.

For example, the grid below listens to the 'keydown' event. If you press Ctrl+Delete, it shows a prompt and deletes the current row. Note that:

  1. The event listener is added with the capture parameter set to true, so it is called before the grid gets it, and
  2. The event handler calls the event's preventDefault method, so the grid does not handle the Delete key as it normally would.

Press Ctrl+Delete to remove the current row:

import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; import * as grid from '@grapecity/wijmo.grid'; import * as input from '@grapecity/wijmo.input'; import * as wijmo from '@grapecity/wijmo'; import { getData } from './data'; document.readyState === 'complete' ? init() : window.onload = init; function init() { // create the grid let theGrid = new grid.FlexGrid('#theGrid', { itemsSource: getData(), allowAddNew: true }); // use ctrl+Delete to delete the current row let theDialog = new input.Popup('#theDialog'); theGrid.hostElement.addEventListener('keydown', e => { let view = theGrid.collectionView; // looking for ctrl+Delete if (e.ctrlKey && e.keyCode == wijmo.Key.Delete && view.currentItem) { // prevent the grid from getting the key e.preventDefault(); // confirm row deletion theDialog.show(true, (sender) => { // delete the row if (sender.dialogResult == 'wj-hide-ok') { view.remove(view.currentItem); } // return focus to the grid theGrid.focus(); }); } }, true); } <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Popup (Delete Rows with Ctrl+Delete)</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div class="container-fluid"> <div id="theGrid"></div> <div id="theDialog" style="display:none"> <div class="wj-dialog-header"> Deleting Row </div> <div class="wj-dialog-body" tabindex="-1"> Do you really want to delete this row? </div> <div class="wj-dialog-footer"> <button class="btn btn-primary wj-hide-ok">Yes</button> <button class="btn btn-default wj-hide">No</button> </div> </div> </div> </body> </html> // grab the event before the grid // // generate some random data export function getData() { let countries = ['US', 'Canada', 'Mexico', 'Germany', 'UK', 'France', 'Italy', 'Greece', 'Holland', 'Japan', 'Korea', 'China'], data = []; // for (let i = 0; i < 1000; i++) { data.push({ id: i, country: countries[i % countries.length], sales: Math.random() * 10000, expenses: Math.random() * 5000, active: i % 3 == 0 }); } // return data; } .wj-flexgrid { height: 300px; margin: 10px 0; } body { margin-bottom: 24pt; } import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; // import * as wijmo from '@grapecity/wijmo'; import * as input from '@grapecity/wijmo.input'; import * as grid from '@grapecity/wijmo.grid'; // import { Component, enableProdMode, NgModule, ViewChild, Inject } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { BrowserModule } from '@angular/platform-browser'; import { WjInputModule } from '@grapecity/wijmo.angular2.input'; import { WjGridModule } from '@grapecity/wijmo.angular2.grid'; import { DataService } from './app.data'; // @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { @ViewChild('thePopup') thePopup: input.Popup; data: any; // constructor(@Inject(DataService) private dataService: DataService) { this.data = dataService.getData(); } // initGrid(grid: grid.FlexGrid) { grid.hostElement.addEventListener('keydown', e => { let view = grid.collectionView; // // looking for ctrl+Delete if (e.ctrlKey && e.keyCode == wijmo.Key.Delete && view.currentItem) { // prevent the grid from getting the key e.preventDefault(); // // confirm row deletion this.thePopup.show(true, (sender: input.Popup) => { // delete the row if (sender.dialogResult == 'wj-hide-ok') { (<wijmo.CollectionView>view).remove(view.currentItem); } // // return focus to the grid grid.focus(); }); } }, true); } } // @NgModule({ imports: [WjInputModule, WjGridModule, BrowserModule], declarations: [AppComponent], providers: [DataService], bootstrap: [AppComponent] }) export class AppModule { } // enableProdMode(); // Bootstrap application with hash style navigation and global services. platformBrowserDynamic().bootstrapModule(AppModule); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Popup (Delete Rows with Ctrl+Delete)</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Polyfills --> <script src="node_modules/core-js/client/shim.min.js"></script> <script src="node_modules/zone.js/dist/zone.min.js"></script> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.js"></script> <script src="systemjs.config.js"></script> <script> // workaround to load 'rxjs/operators' from the rxjs bundle System.import('rxjs').then(function (m) { System.set(SystemJS.resolveSync('rxjs/operators'), System.newModule(m.operators)); System.import('./src/app.component'); }); </script> </head> <body> <app-component></app-component> </body> </html> <div class="container-fluid"> <wj-flex-grid #theGrid [itemsSource]="data" [allowAddNew]="true" (initialized)="initGrid(theGrid)"></wj-flex-grid> <wj-popup #thePopup> <div class="wj-dialog-header"> Deleting Row </div> <div class="wj-dialog-body" tabindex="-1"> Do you really want to delete this row? </div> <div class="wj-dialog-footer"> <button class="btn btn-primary wj-hide-ok">Yes</button> <button class="btn btn-default wj-hide">No</button> </div> </wj-popup> </div> import { Injectable } from '@angular/core'; // @Injectable() export class DataService { getData() { let countries = ['US', 'Canada', 'Mexico', 'Germany', 'UK', 'France', 'Italy', 'Greece', 'Holland', 'Japan', 'Korea', 'China'], data = []; // for (let i = 0; i < 1000; i++) { data.push({ id: i, country: countries[i % countries.length], sales: Math.random() * 10000, expenses: Math.random() * 5000, active: i % 3 == 0 }); } // return data; } } .wj-flexgrid { height: 300px; margin: 10px 0; } body { margin-bottom: 24pt; } <template> <div class="container-fluid"> <wj-flex-grid :itemsSource="data" :allowAddNew="true" :initialized="initGrid"></wj-flex-grid> <wj-popup :initialized="initPopup"> <div class="wj-dialog-header"> Deleting Row </div> <div class="wj-dialog-body" tabindex="-1"> Do you really want to delete this row? </div> <div class="wj-dialog-footer"> <button class="btn btn-primary wj-hide-ok">Yes</button> <button class="btn btn-default wj-hide">No</button> </div> </wj-popup> </div> </template> <script> import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import Vue from 'vue'; import '@grapecity/wijmo.vue2.core'; import '@grapecity/wijmo.vue2.input'; import '@grapecity/wijmo.vue2.grid'; import { getData } from './data'; let App = Vue.extend({ name: 'app', data: function(){ return { thePopup: {}, data: getData() } }, methods: { initPopup: function(popup){ this.thePopup = popup; }, initGrid: function(grid) { grid.hostElement.addEventListener('keydown', e => { let view = grid.collectionView; // looking for ctrl+Delete if (e.ctrlKey && e.keyCode == wijmo.Key.Delete && view.currentItem) { // prevent the grid from getting the key e.preventDefault(); // confirm row deletion this.thePopup.show(true, (sender) => { // delete the row if (sender.dialogResult == 'wj-hide-ok') { view.remove(view.currentItem); } // return focus to the grid grid.focus(); }); } }, true); } } }) let vm = new Vue({ render: h => h(App) }).$mount('#app'); </script> <style> .container-fluid .wj-flexgrid { height: 300px; margin: 10px 0; } body { margin-bottom: 24pt; } </style> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Popup (Delete Rows with Ctrl+Delete)</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app.vue'); </script> </head> <body> <div id="app"></div> </body> </html> // grab the event before the grid // // generate some random data export function getData() { let countries = ['US', 'Canada', 'Mexico', 'Germany', 'UK', 'France', 'Italy', 'Greece', 'Holland', 'Japan', 'Korea', 'China'], data = []; // for (let i = 0; i < 1000; i++) { data.push({ id: i, country: countries[i % countries.length], sales: Math.random() * 10000, expenses: Math.random() * 5000, active: i % 3 == 0 }); } // return data; } import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './app.css'; // import * as React from 'react'; import * as ReactDOM from 'react-dom'; // import * as wjGrid from '@grapecity/wijmo.react.grid'; import * as wijmo from '@grapecity/wijmo'; import * as wjInput from '@grapecity/wijmo.react.input'; import { getData } from './data'; // class App extends React.Component { constructor(props) { super(props); this.initPopup = (popup) => { this.setState({ thePopup: popup }); }; this.initGrid = (grid) => { grid.hostElement.addEventListener('keydown', e => { let view = grid.collectionView; // looking for ctrl+Delete if (e.ctrlKey && e.keyCode == wijmo.Key.Delete && view.currentItem) { // prevent the grid from getting the key e.preventDefault(); // confirm row deletion this.state.thePopup.show(true, (sender) => { // delete the row if (sender.dialogResult == 'wj-hide-ok') { view.remove(view.currentItem); } // return focus to the grid grid.focus(); }); } }, true); }; this.state = { data: getData(), thePopup: {}, }; } render() { return <div className="container-fluid"> <wjGrid.FlexGrid allowAddNew={true} itemsSource={this.state.data} initialized={this.initGrid}> </wjGrid.FlexGrid> <wjInput.Popup initialized={this.initPopup}> <div className="wj-dialog-header"> Deleting Row </div> <div className="wj-dialog-body"> Do you really want to delete this row? </div> <div className="wj-dialog-footer"> <button className="btn btn-primary wj-hide-ok">Yes</button> <button className="btn btn-default wj-hide">No</button> </div> </wjInput.Popup> </div>; } } ReactDOM.render(<App />, document.getElementById('app')); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>AutoComplete</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div id="app"></div> </body> </html> .wj-flexgrid { height: 300px; margin: 10px 0; } body { margin-bottom: 24pt; } export function getData() { let countries = ['US', 'Canada', 'Mexico', 'Germany', 'UK', 'France', 'Italy', 'Greece', 'Holland', 'Japan', 'Korea', 'China'], data = []; // for (let i = 0; i < 1000; i++) { data.push({ id: i, country: countries[i % countries.length], sales: Math.random() * 10000, expenses: Math.random() * 5000, active: i % 3 == 0 }); } // return data; }