-
Data Grids / Data Management
-
Data Grid
- Overview
-
Data Binding
-
Filtering
- Sorting
-
Editing
-
Grouping
-
Selection
- Focused Row
- Paging
-
Scrolling
-
Columns
-
Master-Detail
-
Data Summaries
-
Drag & Drop
-
Export to PDF
-
Export to Excel
- Appearance
-
Customization
- State Persistence
-
Adaptability
-
Keyboard Navigation
- Right-To-Left Support
-
Tree List
- Overview
-
Data Binding
-
Filtering
- Sorting
-
Editing
-
Selection
- Focused Row
- Paging
-
Columns
- Drag & Drop
- State Persistence
- Adaptability
-
Keyboard Navigation
-
Card View
-
Pivot Grid
- Overview
-
Data Binding
-
Field Management
-
Data Summaries
- Drill Down
- Filtering
-
Scrolling
-
Export to Excel
- Chart Integration
- Customization
- State Persistence
-
Filter Builder
-
-
Data Visualization
-
Charts
- Overview
-
Data Binding
-
Common Concepts
-
Axis
-
Aggregation
-
Tooltips
-
Selection
-
Customization
-
Zooming
-
Export
-
-
Area Charts
-
Bar Charts
- Bullet Charts
-
Doughnut Charts
-
Financial Charts
-
Funnel and Pyramid Charts
-
Line Charts
- Pareto Chart
-
Pie Charts
-
Point Charts
-
Polar and Radar Charts
-
Range Charts
- Sankey Chart
-
Sparkline Charts
-
Tree Map
-
Gauges
- Overview
-
Runtime update
-
Bar Gauge
-
Circular Gauge
-
Linear Gauge
-
Diagram
- Overview
-
Data Binding
-
Featured Shapes
-
Custom Shapes
-
Document Capabilities
-
User Interaction
- UI Customization
- Adaptability
-
-
Scheduling / Planning
-
Scheduler
- Overview
-
Data Binding
-
Views
-
Appointments
-
Timetable
- Editing
-
Grouping
- Virtual Scrolling
- Drag & Drop
-
Customization
- Adaptability
-
Gantt
- Overview
- Data Binding
-
Filtering
- Sorting
- Strip Lines
- Export to PDF
- Validation
-
Customization
-
-
Reporting
-
AI-powered Extensions
-
Interaction
-
Report Types
-
Data binding
-
Real-life Reports
-
Layout Features
-
Report Controls
-
Web-specific Features
-
-
Rich Text Editor
- Overview
- Load/Save
- Document Protection
-
Templates
- Autocorrect
-
Customization
- Simple View
-
Spreadsheet
- Overview
-
Open a Document
- Export And Printing
-
Features
-
UI Customization
-
Messaging
-
WYSIWYG Editor
-
Forms
-
Data Editors
- Overview
-
Common Concepts
-
Calendar
- Check Box
- Color Box
- Date Box
-
Date Range Box
-
Number Box
- Radio Group
-
Range Selector
- Range Slider
- Slider
- Speech To Text
- Switch
- Text Area
- Text Box
-
Drop-Downs
- Autocomplete
-
Drop Down Box
-
Select Box
-
Tag Box
-
Lookup
-
Buttons
-
File Upload / File Management
-
File Manager
- Overview
-
File System Types
-
Customization
-
File Uploader
-
-
Popup and Notifications
-
Navigation
- Overview
- Accordion
-
Context Menu
-
Menu
- Multi View
-
Drawer
-
Tab Panel
-
Tabs
-
Toolbar
-
Stepper
- Pagination
-
List
-
Tree View
- Right-to-Left Support
-
Layout
-
Tile View
- Splitter
-
Gallery
- Scroll View
-
-
Interactive Wrappers
-
Sortable
- Resizable
-
-
Progress Indicators
-
Maps
- Overview
-
Map
-
Vector Map
-
Data Binding
- Multiple Layers
-
Markers
- Legend
-
Zooming and Panning
-
Customization
-
-
Localization
Diagram - Templates with Editing
In this demo, the CustomShapeTemplate method defines a common shape template and adds the Edit and Delete links to a shape. These links allow users to modify and remove employee data from the data source. The Diagram component reloads modified diagram data whenever the data source changes.
The OnRequestLayoutUpdate function specifies whether the component must reapply its auto layout once the diagram is reloaded.
The CustomDataExpr method links custom employee information from the data source to diagram nodes. Changes made to data are reflected in the diagram's history. Undo and redo actions (available within the control's UI) allow users to rollback/reapply changes.
The CustomShapeToolboxTemplate method specifies the template used for a shape within the toolbox.
@model IEnumerable<DevExtreme.NETCore.Demos.Models.OrgItemPlain>@(Html.DevExtreme().Diagram() .ID("diagram") .OnRequestLayoutUpdate("onRequestLayoutUpdate") .CustomShapes(cs => { cs.Add() .Type("employee") .Category("employee") .BaseType("rectangle") .Title("New Employee") .DefaultWidth(1.5) .DefaultHeight(1) .ToolboxWidthToHeightRatio(2) .MinWidth(1.5) .MinHeight(1) .MaxWidth(3) .MaxHeight(2) .AllowEditText(false); }) .CustomShapeTemplate(@<text> <svg class="template"> <text class="template-name" x="50%" y="20%"><%- dataItem ? dataItem.FullName : "Employee's Name" %></text> <text class="template-title" x="50%" y="45%"><%- dataItem ? dataItem.Title : "Employee's Title" %></text> <text class="template-button" x="40%" y="85%" onclick="editEmployee(<%- dataItem && JSON.stringify(dataItem) %>)">Edit</text> <text class="template-button" x="62%" y="85%" onclick="deleteEmployee(<%- dataItem && JSON.stringify(dataItem) %>)">Delete</text> </svg> </text>) .CustomShapeToolboxTemplate(@<text> <svg class="template"> <text x="50%" y="40%">New</text> <text x="50%" y="70%">Employee</text> </svg> </text>) .Nodes(ns => ns .DataSource(d => d .Array() .Key("ID") .Data(Model) .OnInserting("onNodeInserting") ) .KeyExpr("ID") .TypeExpr(new JS("itemTypeExpr")) .CustomDataExpr(new JS("itemCustomDataExpr")) .ParentKeyExpr("HeadID") .AutoLayout(al => al .Type(DiagramDataLayoutType.Tree) ) ) .ContextToolbox(ct => ct .ShapeIconsPerRow(1) .Width(100) ) .Toolbox(tb => tb .Groups(g => { g.Add().Category("employee").Title("Employee").Expanded(true); }) .ShowSearch(false) .ShapeIconsPerRow(1) ) .PropertiesPanel(pp => pp .Tabs(t => { t.Add() .Groups(g => { g.Add() .Title("Page Properties") .Commands(new[] { DiagramCommand.PageSize, DiagramCommand.PageOrientation, DiagramCommand.PageColor }); }); }) ))@(Html.DevExtreme().Popup() .ID("popup") .Width(400) .Height(480) .ShowTitle(true) .Title("Edit Employee") .Visible(false) .DragEnabled(false) .ContentTemplate(new TemplateName("popup-content")))@using(Html.DevExtreme().NamedTemplate("popup-content")) { <div class="dx-fieldset"> <div class="dx-field"> <div class="dx-field-label">Name</div> <div class="dx-field-value" data-field="FullName"> @(Html.DevExtreme().TextBox().InputAttr("aria-label", "Full Name")) </div> </div> <div class="dx-field"> <div class="dx-field-label">Title</div> <div class="dx-field-value" data-field="Title"> @(Html.DevExtreme().TextBox().InputAttr("aria-label", "Title")) </div> </div> <div class="dx-field"> <div class="dx-field-label">City</div> <div class="dx-field-value" data-field="City"> @(Html.DevExtreme().TextBox().InputAttr("aria-label", "City")) </div> </div> <div class="dx-field"> <div class="dx-field-label">State</div> <div class="dx-field-value" data-field="State"> @(Html.DevExtreme().TextBox().InputAttr("aria-label", "State")) </div> </div> <div class="dx-field"> <div class="dx-field-label">Email</div> <div class="dx-field-value" data-field="Email"> @(Html.DevExtreme().TextBox().InputAttr("aria-label", "Email")) </div> </div> <div class="dx-field"> <div class="dx-field-label">Skype</div> <div class="dx-field-value" data-field="Skype"> @(Html.DevExtreme().TextBox().InputAttr("aria-label", "Skype")) </div> </div> <div class="dx-field"> <div class="dx-field-label">Phone</div> <div class="dx-field-value" data-field="MobilePhone"> @(Html.DevExtreme().TextBox().InputAttr("aria-label", "Phone")) </div> </div> </div> <div class="dx-fieldset buttons"> @(Html.DevExtreme().Button() .Text("Update") .Type(ButtonType.Default) .OnClick("updateEmployee") ) @(Html.DevExtreme().Button() .Text("Cancel") .OnClick("cancelEditEmployee") ) </div>}<script type="text/javascript"> var currentEmployee = {}; var generatedID = 100; function onNodeInserting(values) { values.ID = values.ID || generatedID++; values.FullName = values.FullName || "Employee's Name"; values.Title = values.Title || "Employee's Title"; } function itemTypeExpr(obj) { return "employee"; } function itemCustomDataExpr(obj, value) { if(value === undefined) { return { "FullName": obj.FullName, "Prefix": obj.Prefix, "Title": obj.Title, "City": obj.City, "State": obj.State, "Email": obj.Email, "Skype": obj.Skype, "MobilePhone": obj.MobilePhone }; } else { obj.FullName = value.FullName; obj.Prefix = value.Prefix; obj.Title = value.Title; obj.City = value.City; obj.State = value.State; obj.Email = value.Email; obj.Skype = value.Skype; obj.MobilePhone = value.MobilePhone; } } function onRequestLayoutUpdate(e) { for(var i = 0; i < e.changes.length; i++) { if(e.changes[i].type === 'remove') e.allowed = true; else if(e.changes[i].data.HeadID !== undefined && e.changes[i].data.HeadID !== null) e.allowed = true; } } function editEmployee(employee) { currentEmployee = Object.assign({}, employee); var popup = $("#popup").dxPopup("instance"); popup.show(); popup.content().find(".dx-field-value").each(function() { var field = $(this).attr("data-field"); var edit = $(this).children().dxTextBox("instance"); edit.option({ value: currentEmployee[field], onValueChanged: function(e) { handleChange(field, e.value); } }); }); }; function deleteEmployee(employee) { var diagram = $("#diagram").dxDiagram("instance"); diagram.getNodeDataSource().store().push([{ type: 'remove', key: employee.ID }]); }; function updateEmployee() { var diagram = $("#diagram").dxDiagram("instance"); diagram.getNodeDataSource().store().push([{ type: 'update', key: currentEmployee.ID, data: { "FullName": currentEmployee.FullName, "Title": currentEmployee.Title, "City": currentEmployee.City, "State": currentEmployee.State, "Email": currentEmployee.Email, "Skype": currentEmployee.Skype, "MobilePhone": currentEmployee.MobilePhone } }]); var popup = $("#popup").dxPopup("instance"); popup.hide(); }; function cancelEditEmployee() { currentEmployee = {}; var popup = $("#popup").dxPopup("instance"); popup.hide(); } function handleChange(field, value) { currentEmployee[field] = value; }</script>xxxxxxxxxxusing DevExtreme.NETCore.Demos.Models.SampleData;using Microsoft.AspNetCore.Mvc;namespace DevExtreme.NETCore.Demos.Controllers { public class DiagramController : Controller { public ActionResult CustomShapesWithTemplatesWithEditing() { return View(SampleData.OrgItemsPlain); } }}xxxxxxxxxx#diagram { height: 725px;}#diagram .template .template-name { font-weight: bold; text-decoration: underline;}#diagram .template .template-title { font-style: italic;}#diagram .template .template-button { cursor: pointer; font-size: 8pt; fill: navy;}#diagram .template .template-button:hover { text-decoration: underline;}.dx-popup-content { padding: 0;}.dx-popup-content .dx-fieldset.buttons { display: flex; justify-content: flex-end;}.dx-popup-content .dx-fieldset.buttons > * { margin-left: 8px;}