If you have technical questions, please create a support ticket in the DevExpress Support Center.
import React, { useCallback, useState } from 'react';
import HtmlEditor, {
TableContextMenu,
TableResizing,
Toolbar,
Item,
} from 'devextreme-react/html-editor';
import { CheckBox, CheckBoxTypes } from 'devextreme-react/check-box';
import { markup } from './data.ts';
export default function App() {
const [allowResizing, setAllowResizing] = useState(true);
const [contextMenuEnabled, setContextMenuEnabled] = useState(true);
const tableResizingChanged = useCallback((e: CheckBoxTypes.ValueChangedEvent) => {
setAllowResizing(e.value);
}, [setAllowResizing]);
const tableContextMenuChanged = useCallback((e: CheckBoxTypes.ValueChangedEvent) => {
setContextMenuEnabled(e.value);
}, [setContextMenuEnabled]);
return (
<div className="widget-container">
<HtmlEditor height="750px" defaultValue={markup}>
<TableContextMenu enabled={contextMenuEnabled} />
<TableResizing enabled={allowResizing} />
<Toolbar>
<Item name="bold" />
<Item name="color" />
<Item name="separator" />
<Item name="alignLeft" />
<Item name="alignCenter" />
<Item name="alignRight" />
<Item name="separator" />
<Item name="insertTable" />
<Item name="insertHeaderRow" />
<Item name="insertRowAbove" />
<Item name="insertRowBelow" />
<Item name="separator" />
<Item name="insertColumnLeft" />
<Item name="insertColumnRight" />
<Item name="separator" />
<Item name="deleteColumn" />
<Item name="deleteRow" />
<Item name="deleteTable" />
<Item name="separator" />
<Item name="cellProperties" />
<Item name="tableProperties" />
</Toolbar>
</HtmlEditor>
<div className="options">
<div className="caption">Options</div>
<div className="option">
<CheckBox
text="Allow Table Resizing"
value={allowResizing}
onValueChanged={tableResizingChanged}
/>
</div>
<div className="option">
<CheckBox
text="Enable Table Context Menu"
value={contextMenuEnabled}
onValueChanged={tableContextMenuChanged}
/>
</div>
</div>
</div>
);
}
xxxxxxxxxx
import React, { useCallback, useState } from 'react';
import HtmlEditor, {
TableContextMenu,
TableResizing,
Toolbar,
Item,
} from 'devextreme-react/html-editor';
import { CheckBox } from 'devextreme-react/check-box';
import { markup } from './data.js';
export default function App() {
const [allowResizing, setAllowResizing] = useState(true);
const [contextMenuEnabled, setContextMenuEnabled] = useState(true);
const tableResizingChanged = useCallback(
(e) => {
setAllowResizing(e.value);
},
[setAllowResizing],
);
const tableContextMenuChanged = useCallback(
(e) => {
setContextMenuEnabled(e.value);
},
[setContextMenuEnabled],
);
return (
<div className="widget-container">
<HtmlEditor
height="750px"
defaultValue={markup}
>
<TableContextMenu enabled={contextMenuEnabled} />
<TableResizing enabled={allowResizing} />
<Toolbar>
<Item name="bold" />
<Item name="color" />
<Item name="separator" />
<Item name="alignLeft" />
<Item name="alignCenter" />
<Item name="alignRight" />
<Item name="separator" />
<Item name="insertTable" />
<Item name="insertHeaderRow" />
<Item name="insertRowAbove" />
<Item name="insertRowBelow" />
<Item name="separator" />
<Item name="insertColumnLeft" />
<Item name="insertColumnRight" />
<Item name="separator" />
<Item name="deleteColumn" />
<Item name="deleteRow" />
<Item name="deleteTable" />
<Item name="separator" />
<Item name="cellProperties" />
<Item name="tableProperties" />
</Toolbar>
</HtmlEditor>
<div className="options">
<div className="caption">Options</div>
<div className="option">
<CheckBox
text="Allow Table Resizing"
value={allowResizing}
onValueChanged={tableResizingChanged}
/>
</div>
<div className="option">
<CheckBox
text="Enable Table Context Menu"
value={contextMenuEnabled}
onValueChanged={tableContextMenuChanged}
/>
</div>
</div>
</div>
);
}
xxxxxxxxxx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
ReactDOM.render(
<App />,
document.getElementById('app'),
);
xxxxxxxxxx
export const markup = `
<h2>
Hardware Upgrade
</h2>
<br>
<table>
<thead>
<tr>
<th style="text-align: left; width: 320px;">Task Subject</th>
<th style="text-align: center;">Status</th>
<th style="text-align: right;">Progress</th>
</tr>
</thead>
<tbody>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Approve Personal Computer Upgrade Plan</td>
<td style="text-align: center; color: #5cb85c;">
<p style="font-size: 1.15em;">✓</p>
<p>Completed</p>
</td>
<td style="text-align: right;">100%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Prepare workspaces</td>
<td style="text-align: center; color: #5cb85c;">
<p style="font-size: 1.15em;">✓</p>
<p>Completed</p>
</td>
<td style="text-align: right;">100%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Upgrade Server Hardware</td>
<td style="text-align: center;">
<p style="font-size: 1.15em;">⟳</p>
<p>In Progress</p>
</td>
<td style="text-align: right;">45%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Upgrade Personal Computers</td>
<td style="text-align: center; color: #f0ad4e;">
<p style="font-size: 1.15em;">‖</p>
<p>Need Assistance</p>
</td>
<td style="text-align: right;">80%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Replace HDD with SSD</td>
<td style="text-align: center;">
<p style="font-size: 1.15em;">⟳</p>
<p>In Progress</p>
</td>
<td style="text-align: right;">80%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Purchase a New Server</td>
<td style="text-align: center; color: #d9534f;">
<p style="font-size: 1.15em;">✖</p>
<p>Canceled</p>
</td>
<td style="text-align: right;">15%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Purchase Laptops</td>
<td style="text-align: center; color: #5cb85c;">
<p style="font-size: 1.15em;">✓</p>
<p>Completed</p>
</td>
<td style="text-align: right;">100%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Prepare a list of necessary devices for testing</td>
<td style="text-align: center; color: #5cb85c;">
<p style="font-size: 1.15em;">✓</p>
<p>Completed</p>
</td>
<td style="text-align: right;">100%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Purchase devices for testing</td>
<td style="text-align: center; color: #f0ad4e;">
<p style="font-size: 1.15em;">‖</p>
<p>Need Assistance</p>
</td>
<td style="text-align: right;">25%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Recycle Broken Hardware</td>
<td style="text-align: center; color: #5cb85c;">
<p style="font-size: 1.15em;">✓</p>
<p>Completed</p>
</td>
<td style="text-align: right;">100%</td>
</tr>
</tbody>
</table>
<br>
`;
xxxxxxxxxx
window.exports = window.exports || {};
window.config = {
transpiler: 'ts',
typescriptOptions: {
module: 'system',
emitDecoratorMetadata: true,
experimentalDecorators: true,
jsx: 'react',
},
meta: {
'react': {
'esModule': true,
},
'typescript': {
'exports': 'ts',
},
'devextreme/time_zone_utils.js': {
'esModule': true,
},
'devextreme/localization.js': {
'esModule': true,
},
'devextreme/viz/palette.js': {
'esModule': true,
},
'openai': {
'esModule': true,
},
},
paths: {
'npm:': 'https://unpkg.com/',
'bundles:': 'bundles/',
'externals:': 'bundles/externals/',
},
defaultExtension: 'js',
map: {
'ts': 'npm:plugin-typescript@8.0.0/lib/plugin.js',
'typescript': 'npm:typescript@4.2.4/lib/typescript.js',
'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js',
'react': 'npm:react@17.0.2/umd/react.development.js',
'react-dom': 'npm:react-dom@17.0.2/umd/react-dom.development.js',
'prop-types': 'npm:prop-types/prop-types.js',
'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js',
'luxon': 'npm:luxon@3.4.4/build/global/luxon.min.js',
'es6-object-assign': 'npm:es6-object-assign',
'devextreme': 'npm:devextreme@link:../../packages/devextreme/artifacts/npm/devextreme/cjs',
'devextreme-react': 'npm:devextreme-react@link:../../packages/devextreme-react/npm/cjs',
'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js',
'devexpress-diagram': 'npm:devexpress-diagram@2.2.5/dist/dx-diagram.js',
'devexpress-gantt': 'npm:devexpress-gantt@4.1.54/dist/dx-gantt.js',
'@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12',
'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js',
'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js',
'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js',
'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js',
'inferno-hydrate': 'npm:inferno-hydrate/dist/inferno-hydrate.min.js',
'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js',
'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js',
'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js',
'devextreme-cldr-data': 'npm:devextreme-cldr-data@1.0.3',
// SystemJS plugins
'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js',
'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js',
// Prettier
'prettier/standalone': 'npm:prettier@2.8.8/standalone.js',
'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js',
},
packages: {
'devextreme': {
defaultExtension: 'js',
},
'devextreme-react': {
main: 'index.js',
},
'devextreme/events/utils': {
main: 'index',
},
'devextreme/localization/messages': {
format: 'json',
defaultExtension: 'json',
},
'devextreme/events': {
main: 'index',
},
'es6-object-assign': {
main: './index.js',
defaultExtension: 'js',
},
},
packageConfigPaths: [
'npm:@devextreme/*/package.json',
'npm:@devextreme/runtime@3.0.12/inferno/package.json',
],
babelOptions: {
sourceMaps: false,
stage0: true,
react: true,
},
};
System.config(window.config);
xxxxxxxxxx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
ReactDOM.render(<App />, document.getElementById('app'));
xxxxxxxxxx
export const markup = `
<h2>
Hardware Upgrade
</h2>
<br>
<table>
<thead>
<tr>
<th style="text-align: left; width: 320px;">Task Subject</th>
<th style="text-align: center;">Status</th>
<th style="text-align: right;">Progress</th>
</tr>
</thead>
<tbody>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Approve Personal Computer Upgrade Plan</td>
<td style="text-align: center; color: #5cb85c;">
<p style="font-size: 1.15em;">✓</p>
<p>Completed</p>
</td>
<td style="text-align: right;">100%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Prepare workspaces</td>
<td style="text-align: center; color: #5cb85c;">
<p style="font-size: 1.15em;">✓</p>
<p>Completed</p>
</td>
<td style="text-align: right;">100%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Upgrade Server Hardware</td>
<td style="text-align: center;">
<p style="font-size: 1.15em;">⟳</p>
<p>In Progress</p>
</td>
<td style="text-align: right;">45%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Upgrade Personal Computers</td>
<td style="text-align: center; color: #f0ad4e;">
<p style="font-size: 1.15em;">‖</p>
<p>Need Assistance</p>
</td>
<td style="text-align: right;">80%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Replace HDD with SSD</td>
<td style="text-align: center;">
<p style="font-size: 1.15em;">⟳</p>
<p>In Progress</p>
</td>
<td style="text-align: right;">80%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Purchase a New Server</td>
<td style="text-align: center; color: #d9534f;">
<p style="font-size: 1.15em;">✖</p>
<p>Canceled</p>
</td>
<td style="text-align: right;">15%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Purchase Laptops</td>
<td style="text-align: center; color: #5cb85c;">
<p style="font-size: 1.15em;">✓</p>
<p>Completed</p>
</td>
<td style="text-align: right;">100%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Prepare a list of necessary devices for testing</td>
<td style="text-align: center; color: #5cb85c;">
<p style="font-size: 1.15em;">✓</p>
<p>Completed</p>
</td>
<td style="text-align: right;">100%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Purchase devices for testing</td>
<td style="text-align: center; color: #f0ad4e;">
<p style="font-size: 1.15em;">‖</p>
<p>Need Assistance</p>
</td>
<td style="text-align: right;">25%</td>
</tr>
<tr style="text-align: center;">
<td style="text-align: left; width: 320px;">Recycle Broken Hardware</td>
<td style="text-align: center; color: #5cb85c;">
<p style="font-size: 1.15em;">✓</p>
<p>Completed</p>
</td>
<td style="text-align: right;">100%</td>
</tr>
</tbody>
</table>
<br>
`;
xxxxxxxxxx
<html lang="en">
<head></head>
<body class="dx-viewport">
<div class="demo-container">
<div id="app"></div>
</div>
</body>
</html>
xxxxxxxxxx
.demo-container {
height: 950px;
}
.options {
padding: 20px;
background-color: rgba(191, 191, 191, 0.15);
margin-top: 20px;
}
.caption {
font-size: 18px;
font-weight: 500;
}
.option {
margin-top: 10px;
}
Manage Tables with the Built-in Toolbar
To manage tables via a built-in toolbar, add the following items to it:
-
"insertTable" / "deleteTable"
Manage a table. -
"insertRowAbove" / "insertRowBelow" / "deleteRow"
Manage rows. -
"insertColumnLeft" / "insertColumnRight" / "deleteColumn"
Manage columns. -
"tableProperties" / "cellProperties"
Open a pop-up window with table or cell customization options.
Manage Tables with the Context Menu
To manage table layouts with the context menu, set the tableContextMenu.enabled property to true. In this demo, you can click the Enable Table Context Menu check box under the HtmlEditor to enable or disable this property. When it is enabled, right-click a table cell to open the context menu.
The context menu cannot be used to create new tables. The menu is only available within table boundaries. If you want users to create tables, add an "insertTable" item to the toolbar.
If you need to customize menu commands, override the tableContextMenu.items array. Refer to its description for a code example.
Manage Tables Programmatically
You can perform table-related actions in code. Use the getModule method to access the Table module. This module contains methods with names that match toolbar item names listed above. Refer to the following topic for the complete method list and code examples: DevExtreme Quill modules: Table.
Resize Tables
If you want to resize table rows and columns, set the tableResizing.enabled property to true. In this demo, you can use the Allow Table Resizing check box to change the property value.
You can also set the tableResizing.minColumnWidth and tableResizing.minRowHeight properties to specify minimum column width and row height. If you do not set these properties, width and height are determined by cell content. This demo illustrates the latter behavior (when you reduce column width or row height to small values).