Your search did not match any results.

Form - Smart Paste

The DevExtreme Form ships with AI-powered Smart Paste functionality. When a user copies unstructured text from external sources such as documents, spreadsheets, web pages, or emails, Smart Paste processes clipboard data and populates related form fields automatically.

Backend API
@section ExternalDependencies { <script type="module"> import { AzureOpenAI } from "https://esm.sh/openai@4.73.1"; window.AzureOpenAI = AzureOpenAI; </script> } @using DevExtreme.MVC.Demos.ViewModels @{ var textAreaText = @"Payment: Amount - $123.00 Statement Date: 10/15/2024 Name: John Smith Contact: (123) 456-7890 Email: john@myemail.com Address: - 123 Elm St Apt 4B - New York, NY 10001"; } <div id="textarea-label" class="instruction"> Copy text from the editor below to the clipboard. Edit the text to see how your changes affect Smart Paste result. </div> <div class="instruction"> Paste text from the clipboard to populate the form. Press Ctrl+Shift+V (when the form is focused) or use the "Smart Paste" button under the form. </div> <div class="textarea-container"> @(Html.DevExtreme().Button() .Text("Copy Text") .Icon("copy") .Type("default") .StylingMode(ButtonStylingMode.Contained) .Width("fit-content") .OnClick("onCopy") ) @(Html.DevExtreme().TextArea() .ID("textarea") .Value(textAreaText) .InputAttr("aria-labelledby", "textarea-label") .StylingMode(EditorStylingMode.Filled) .Height("100%") ) </div> @(Html.DevExtreme().Form<SmartPasteFormViewModel>() .ID("form") .AiIntegration(new JS("aiIntegration")) .LabelMode(FormLabelMode.Outside) .LabelLocation(FormLabelLocation.Top) .ShowColonAfterLabel(false) .MinColWidth(220) .Items(items => { items.AddGroup() .Caption("Billing Summary") .ColCountByScreen(c => c.Md(2).Sm(2).Lg(2)) .Items(groupItems => { groupItems.AddSimpleFor(m => m.AmountDue) .Editor(e => e .TextBox() .Placeholder("$0.00") .StylingMode(EditorStylingMode.Filled) ) .AiOptions(e => e .Instruction("Format as the following: $0.00") ); groupItems.AddSimpleFor(m => m.StatementDate) .Editor(e => e .DateBox() .Placeholder("MM/DD/YYYY") .StylingMode(EditorStylingMode.Filled) ) .AiOptions(e => e .Instruction("Format as the following: MM/DD/YYYY") ) .IsRequired(false); }); items.AddGroup() .Caption("Billing Information") .ColCountByScreen(c => c.Md(2).Sm(2).Lg(2)) .Items(groupItems => { groupItems.AddSimpleFor(m => m.FirstName) .Editor(e => e .TextBox() .StylingMode(EditorStylingMode.Filled) ); groupItems.AddSimpleFor(m => m.LastName) .Editor(e => e .TextBox() .StylingMode(EditorStylingMode.Filled) ); groupItems.AddSimpleFor(m => m.PhoneNumber) .Editor(e => e .TextBox() .Placeholder("(000) 000-0000") .StylingMode(EditorStylingMode.Filled) ) .AiOptions(e => e .Instruction("Format as the following: (000) 000-0000") ); groupItems.AddSimpleFor(m => m.Email) .Editor(e => e .TextBox() .StylingMode(EditorStylingMode.Filled) ) .ValidationRules( vr => { vr.AddEmail(); } ) .AiOptions(e => e .Instruction("Do not fill this field if the text contains an invalid email address. A valid email is in the following format: email@example.com") ); }); items.AddGroup() .Caption("Billing Address") .ColCountByScreen(c => c.Md(2).Sm(2).Lg(2)) .Items(groupItems => { groupItems.AddSimpleFor(m => m.StreetAddress) .Editor(e => e .TextBox() .StylingMode(EditorStylingMode.Filled) ); groupItems.AddSimpleFor(m => m.City) .Editor(e => e .TextBox() .StylingMode(EditorStylingMode.Filled) ); groupItems.AddSimpleFor(m => m.State) .DataField("State/Province/Region") .Editor(e => e .TextBox() .StylingMode(EditorStylingMode.Filled) ); groupItems.AddSimpleFor(m => m.ZIP) .Editor(e => e .TextBox() .StylingMode(EditorStylingMode.Filled) ) .AiOptions(e => e .Instruction("If the text does not contain a ZIP, determine the ZIP code from the provided address.") ); }); items.AddGroup() .ColCountByScreen(c => c.Md(2).Sm(2).Lg(2)) .CssClass("buttons-group") .Items(groupItems => { groupItems.AddButton().Name("smartPaste") .ButtonOptions(b => b .Type(ButtonType.Default) .StylingMode(ButtonStylingMode.Contained) ); groupItems.AddButton().Name("reset") .ButtonOptions(b => b .Type(ButtonType.Normal) .StylingMode(ButtonStylingMode.Outlined) ); }); }) ) <script> let aiService; const deployment = 'gpt-4o-mini'; const apiVersion = '2024-02-01'; const endpoint = 'https://public-api.devexpress.com/demo-openai'; const apiKey = 'DEMO'; async function getAIResponse(messages, signal) { const params = { messages, model: deployment, max_tokens: 1000, temperature: 0.7, }; return aiService.chat.completions.create(params, { signal }); } const aiIntegration = new DevExpress.aiIntegration({ sendRequest({ prompt }) { const controller = new AbortController(); const signal = controller.signal; const aiPrompt = [ { role: 'system', content: prompt.system, }, { role: 'user', content: prompt.user, }, ]; const promise = new Promise(async (resolve, reject) => { try { const response = await getAIResponse(aiPrompt, signal); const result = response.choices[0].message?.content; resolve(result); } catch { showNotification('Something went wrong. Please try again.', '#form', true); reject(); } }); const result = { promise, abort: () => { controller.abort(); }, }; return result; }, }); $(() => { aiService = new AzureOpenAI({ dangerouslyAllowBrowser: true, deployment, endpoint, apiVersion, apiKey, }); const form = $('#form').dxForm('instance'); form.registerKeyHandler('V', (event) => { if (event.ctrlKey && event.shiftKey) { navigator.clipboard.readText() .then((text) => { if (text) { form.smartPaste(text); } else { showNotification( 'Clipboard is empty. Copy text before pasting', '#form', ); } }) .catch(() => { showNotification( 'Could not access the clipboard', '#form', ); }); } }); }); function showNotification(message, of, isError, offset) { DevExpress.ui.notify({ message, position: { my: 'bottom center', at: 'bottom center', of, offset: offset ?? '0 -50', }, width: 'fit-content', maxWidth: 'fit-content', minWidth: 'fit-content', }, isError ? 'error' : 'info', 1500); }; function onCopy(data) { const textAreaText = $('#textarea').dxTextArea('instance').option('value'); navigator.clipboard.writeText(textAreaText); showNotification('Text copied to clipboard', "#textarea", false, '0 -20'); } </script>
using DevExtreme.AspNet.Data; using DevExtreme.AspNet.Mvc; using DevExtreme.MVC.Demos.Models.SampleData; using DevExtreme.MVC.Demos.ViewModels; using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; using System.Web.Mvc; namespace DevExtreme.MVC.Demos.Controllers { public class FormController : Controller { public ActionResult SmartPaste() { return View(new SmartPasteFormViewModel {}); } } }
using System; using System.Collections.Generic; namespace DevExtreme.MVC.Demos.ViewModels { public class FormViewModel { public int ID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string CompanyName { get; set; } public string Position { get; set; } public string OfficeNo { get; set; } public DateTime BirthDate { get; set; } public DateTime HireDate { get; set; } public string Address { get; set; } public string City { get; set; } public string State { get; set; } public string Zipcode { get; set; } public string Phone { get; set; } public string Email { get; set; } public string Skype { get; set; } public string Notes { get; set; } } public class DynamicFormViewModel { public string FirstName { get; set; } public string LastName { get; set; } public string Address { get; set; } public string City { get; set; } public List<string> Phones { get; set; } } public class SmartPasteFormViewModel { public string AmountDue { get; set; } public DateTime StatementDate { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string PhoneNumber { get; set; } public string Email { get; set; } public string StreetAddress { get; set; } public string City { get; set; } public string State { get; set; } public string ZIP { get; set; } } }
.demo-container { display: grid; grid-template-columns: 1fr 2fr; grid-template-rows: auto auto; gap: 24px 40px; min-width: 720px; max-width: 900px; margin: auto; } .instruction { color: var(--dx-texteditor-color-label); } .textarea-container { display: flex; flex-direction: column; gap: 16px; } .dx-layout-manager .dx-field-item.dx-last-row { padding-top: 4px; } .dx-toast-info .dx-toast-icon { display: none; } .buttons-group { display: flex; width: 100%; justify-content: end; } .buttons-group .dx-item-content { gap: 8px; } .buttons-group .dx-field-item:not(.dx-first-col), .buttons-group .dx-field-item:not(.dx-last-col) { padding: 0; } .buttons-group .dx-item { flex: unset !important; }

Use the following APIs to activate Smart Paste in our Form component:

  • aiIntegration - accepts an AIIntegration object that contains AI Service settings.
  • 'smartPaste' – adds a built-in Smart Paste button to the Form (see name for additional information). To use this capability in code, call the smartPaste(text) method. This sample leverages this method and implements a custom shortcut to activate Smart Paste.

Configure each Form item using aiOptions:

  • disabled - prevents AI-generated text from being pasted into this item.
  • instruction - specifies item instruction for the AI service.