DevExtreme v24.2 is now available.

Explore our newest features/capabilities and share your thoughts with us.

Your search did not match any results.

React Text Area

The TextArea component enables users to enter and edit multi-line text. This component can have a fixed or resizable height. The component with the fixed height displays a native scroll bar if the entered text exceeds the text area. If you set the autoResizeEnabled property to true, the TextArea automatically resizes its height to fit the text.

DevExtreme Accessibility Compliance
DevExtreme component libraries meet a variety of WCAG and Section 508 compliance standards. To assess this demo’s accessibility level, click the Run AXE® Validation button to launch the AXE® web accessibility evaluation tool.
All trademarks or registered trademarks are property of their respective owners. AXE® Terms of Use
The overall accessibility level of your application depends on the TextArea features used.
Backend API
import React, { useCallback, useState } from 'react'; import CheckBox, { CheckBoxTypes } from 'devextreme-react/check-box'; import SelectBox, { SelectBoxTypes } from 'devextreme-react/select-box'; import TextArea, { TextAreaTypes } from 'devextreme-react/text-area'; import service from './data.ts'; const content = service.getContent(); const { valueChangeEvents } = service; const notesLabel = { 'aria-label': 'Notes' }; const eventLabel = { 'aria-label': 'Event' }; function App() { const [value, setValue] = useState(content); const [valueForEditableTestArea, setValueForEditableTestArea] = useState(content); const [maxLength, setMaxLength] = useState(null); const [eventValue, setEventValue] = useState(valueChangeEvents[0].name); const [autoResizeEnabled, setAutoResizeEnabled] = useState(false); const [height, setHeight] = useState(90); const onCheckboxValueChanged = useCallback((e: CheckBoxTypes.ValueChangedEvent) => { const str = content; setValue(e.value ? str.substring(0, 100) : str); setMaxLength(e.value ? 100 : null); }, []); const onAutoResizeChanged = useCallback((e: CheckBoxTypes.ValueChangedEvent) => { setAutoResizeEnabled(e.value); setHeight(e.value ? undefined : 90); }, []); const onSelectBoxValueChanged = useCallback((e: SelectBoxTypes.ValueChangedEvent) => { setEventValue(e.value); }, []); const onTextAreaValueChanged = useCallback((e: TextAreaTypes.ValueChangedEvent) => { setValueForEditableTestArea(e.value); }, []); return ( <React.Fragment> <div className="dx-fieldset"> <div className="dx-fieldset-header">Default Mode</div> <div className="dx-field"> <CheckBox defaultValue={false} onValueChanged={onCheckboxValueChanged} text="Limit text length" ></CheckBox> </div> <div className="dx-field"> <CheckBox value={autoResizeEnabled} onValueChanged={onAutoResizeChanged} text="Enable auto resize" ></CheckBox> </div> </div> <div className="textarea-wrapper"> <TextArea height={height} maxLength={maxLength} defaultValue={value} inputAttr={notesLabel} autoResizeEnabled={autoResizeEnabled} /> </div> <div className="full-width-content"> <div className="dx-fieldset"> <div className="dx-fieldset-header">Event Handling and API</div> <div className="dx-field"> <div className="dx-field-label">Synchronize text areas </div> <div className="dx-field-value"> <SelectBox items={valueChangeEvents} valueExpr="name" displayExpr="title" inputAttr={eventLabel} value={eventValue} onValueChanged={onSelectBoxValueChanged} /> </div> </div> </div> <div className="textarea-wrapper"> <TextArea height={90} value={valueForEditableTestArea} valueChangeEvent={eventValue} inputAttr={notesLabel} onValueChanged={onTextAreaValueChanged} /> <TextArea height={90} value={valueForEditableTestArea} readOnly={true} inputAttr={notesLabel} valueChangeEvent={eventValue} /> </div> </div> </React.Fragment> ); } export default App;
import React, { useCallback, useState } from 'react'; import CheckBox from 'devextreme-react/check-box'; import SelectBox from 'devextreme-react/select-box'; import TextArea from 'devextreme-react/text-area'; import service from './data.js'; const content = service.getContent(); const { valueChangeEvents } = service; const notesLabel = { 'aria-label': 'Notes' }; const eventLabel = { 'aria-label': 'Event' }; function App() { const [value, setValue] = useState(content); const [valueForEditableTestArea, setValueForEditableTestArea] = useState(content); const [maxLength, setMaxLength] = useState(null); const [eventValue, setEventValue] = useState(valueChangeEvents[0].name); const [autoResizeEnabled, setAutoResizeEnabled] = useState(false); const [height, setHeight] = useState(90); const onCheckboxValueChanged = useCallback((e) => { const str = content; setValue(e.value ? str.substring(0, 100) : str); setMaxLength(e.value ? 100 : null); }, []); const onAutoResizeChanged = useCallback((e) => { setAutoResizeEnabled(e.value); setHeight(e.value ? undefined : 90); }, []); const onSelectBoxValueChanged = useCallback((e) => { setEventValue(e.value); }, []); const onTextAreaValueChanged = useCallback((e) => { setValueForEditableTestArea(e.value); }, []); return ( <React.Fragment> <div className="dx-fieldset"> <div className="dx-fieldset-header">Default Mode</div> <div className="dx-field"> <CheckBox defaultValue={false} onValueChanged={onCheckboxValueChanged} text="Limit text length" ></CheckBox> </div> <div className="dx-field"> <CheckBox value={autoResizeEnabled} onValueChanged={onAutoResizeChanged} text="Enable auto resize" ></CheckBox> </div> </div> <div className="textarea-wrapper"> <TextArea height={height} maxLength={maxLength} defaultValue={value} inputAttr={notesLabel} autoResizeEnabled={autoResizeEnabled} /> </div> <div className="full-width-content"> <div className="dx-fieldset"> <div className="dx-fieldset-header">Event Handling and API</div> <div className="dx-field"> <div className="dx-field-label">Synchronize text areas </div> <div className="dx-field-value"> <SelectBox items={valueChangeEvents} valueExpr="name" displayExpr="title" inputAttr={eventLabel} value={eventValue} onValueChanged={onSelectBoxValueChanged} /> </div> </div> </div> <div className="textarea-wrapper"> <TextArea height={90} value={valueForEditableTestArea} valueChangeEvent={eventValue} inputAttr={notesLabel} onValueChanged={onTextAreaValueChanged} /> <TextArea height={90} value={valueForEditableTestArea} readOnly={true} inputAttr={notesLabel} valueChangeEvent={eventValue} /> </div> </div> </React.Fragment> ); } export default App;
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.tsx'; ReactDOM.render(<App />, document.getElementById('app'));
const valueChangeEvents = [{ title: 'On Change', name: 'change', }, { title: 'On Key Up', name: 'keyup', }]; const content = 'Prepare 2013 Marketing Plan: We need to double revenues in 2013 and our marketing strategy is going to be key here. R&D is improving existing products and creating new products so we can deliver great AV equipment to our customers.Robert, please make certain to create a PowerPoint presentation for the members of the executive team.'; export default { valueChangeEvents, getContent() { return content; }, };
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);
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.js'; ReactDOM.render(<App />, document.getElementById('app'));
const valueChangeEvents = [ { title: 'On Change', name: 'change', }, { title: 'On Key Up', name: 'keyup', }, ]; const content = 'Prepare 2013 Marketing Plan: We need to double revenues in 2013 and our marketing strategy is going to be key here. R&D is improving existing products and creating new products so we can deliver great AV equipment to our customers.Robert, please make certain to create a PowerPoint presentation for the members of the executive team.'; export default { valueChangeEvents, getContent() { return content; }, };
<!DOCTYPE html> <html lang="en"> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/24.2.3/css/dx.light.css" /> <link rel="stylesheet" type="text/css" href="styles.css" /> <script src="https://unpkg.com/core-js@2.6.12/client/shim.min.js"></script> <script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script> <script type="text/javascript" src="config.js"></script> <script type="text/javascript"> System.import("./index.tsx"); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="app"></div> </div> </body> </html>
.full-width-content { width: 100%; margin-top: 30px; } .full-width-content .textarea-wrapper > .dx-widget { margin-bottom: 20px; } .full-width-content .dx-field { max-width: 385px; } .textarea-wrapper { padding: 0 20px; }

You can also specify the maxLength property to limit the number of characters a user can enter. Note that this property only limits the number of characters for users. You can enter text that exceeds the maximum character length programmatically, but the number of characters displayed to users will still be limited by this property setting.

The TextArea stores the text in the value property and updates it after the DOM event occurs. To specify which DOM event to use instead of the default "change" event, use the valueChangeEvent property. To handle the value change, use the TextArea's onValueChanged function.

Change the text in the Event Handling and API section below to see how this feature works. Use the "Synchronize text areas" drop-down menu to select which event updates the read-only component's value: "change" or "keyup".