Skip to content

Commit cb965e6

Browse files
892709: CRUD support in diagram control
1 parent 9542159 commit cb965e6

File tree

1 file changed

+331
-1
lines changed

1 file changed

+331
-1
lines changed

blazor/diagram/data-binding.md

Lines changed: 331 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,335 @@ The following sample code demonstrates how to bind data to the Diagram component
10211021
```
10221022
You can download a complete working sample from [GitHub](https://github.com/SyncfusionExamples/Blazor-Diagram-Examples/tree/master/UG-Samples/DataBinding/RemoteData/URLAdaptor)
10231023
1024+
### How to bind custom data
1025+
The custom data binding can be performed in the diagram component by providing the custom adaptor class and overriding the Read or ReadAsync method of the DataAdaptor abstract class.
1026+
1027+
The following sample code demonstrates implementing custom data binding using custom adaptor,
1028+
1029+
```cshtml
1030+
@using Syncfusion.Blazor
1031+
@using Syncfusion.Blazor.Diagram
1032+
@using Syncfusion.Blazor.Data
1033+
1034+
<div class="row" id="diagram">
1035+
<div class="col-md-10">
1036+
<div id="diagram-space" class="content-wrapper">
1037+
<SfDiagramComponent ID="diagramControl" @ref="@diagram" Width="100%" Height="690px" ConnectorCreating="@ConnectorCreating" NodeCreating="@NodeCreating">
1038+
<DataSourceSettings ID="EmployeeID" ParentID="ReportsTo">
1039+
<SfDataManager AdaptorInstance="@typeof(CustomAdaptor)" Adaptor="Adaptors.CustomAdaptor"></SfDataManager>
1040+
</DataSourceSettings>
1041+
<Layout Type="Syncfusion.Blazor.Diagram.LayoutType.HierarchicalTree" VerticalSpacing="75" HorizontalSpacing="75"></Layout>
1042+
</SfDiagramComponent>
1043+
</div>
1044+
</div>
1045+
</div>
1046+
@functions{
1047+
SfDiagramComponent? diagram;
1048+
public static List<EmployeeDetails> employeeDetails { get; set; }
1049+
Layout LayoutValue = new Layout() { };
1050+
private TreeInfo GetLayoutInfo(IDiagramObject obj, TreeInfo options)
1051+
{
1052+
options.EnableSubTree = true;
1053+
options.Orientation = Orientation.Horizontal;
1054+
return options;
1055+
}
1056+
private void NodeCreating(IDiagramObject obj)
1057+
{
1058+
Node? node = obj as Node;
1059+
node!.Style = new ShapeStyle() { Fill = "#659be5", StrokeColor = "none", StrokeWidth = 2, };
1060+
node.BackgroundColor = "#659be5";
1061+
node.Width = 200;
1062+
node.Height = 100;
1063+
EmployeeDetails data = node.Data as EmployeeDetails;
1064+
if (data != null)
1065+
{
1066+
//node.ID = data.FirstName + data.EmployeeID;
1067+
node.Annotations = new DiagramObjectCollection<ShapeAnnotation>()
1068+
{
1069+
new ShapeAnnotation()
1070+
{
1071+
ID = data.FirstName,
1072+
Content = $"Name:{data.FirstName}\nReportsTo:{data.ReportsTo}\nDesignation:{data.Designation}\nCountry:{data.Country}",
1073+
Style = new TextStyle(){FontSize = 15, Color = "white"}
1074+
}
1075+
};
1076+
node.Style = new ShapeStyle() { Fill = data.Color, StrokeColor = "none", StrokeWidth = 2, };
1077+
}
1078+
}
1079+
private void ConnectorCreating(IDiagramObject connector)
1080+
{
1081+
Connector? newConnector = connector as Connector;
1082+
newConnector!.TargetDecorator = new DecoratorSettings() { Shape = DecoratorShape.None };
1083+
newConnector.Type = ConnectorSegmentType.Orthogonal;
1084+
newConnector.Style = new ShapeStyle() { StrokeColor = "#6d6d6d" };
1085+
newConnector.Constraints = ConnectorConstraints.None;
1086+
newConnector.CornerRadius = 5;
1087+
}
1088+
1089+
1090+
public class EmployeeDetails
1091+
{
1092+
public string EmployeeID { get; set; }
1093+
1094+
public string ReportsTo { get; set; }
1095+
1096+
public string FirstName { get; set; }
1097+
1098+
public string Designation { get; set; }
1099+
1100+
public string Country { get; set; }
1101+
1102+
public string Color { get; set; }
1103+
}
1104+
1105+
1106+
// Implementing custom adaptor by extending the DataAdaptor class
1107+
public class CustomAdaptor : DataAdaptor
1108+
{
1109+
// Performs data Read operation
1110+
public override object Read(DataManagerRequest dm, string key = null)
1111+
{
1112+
IEnumerable<EmployeeDetails> DataSource = employeeDetails;
1113+
if (dm.Search != null && dm.Search.Count > 0)
1114+
{
1115+
// Searching
1116+
DataSource = DataOperations.PerformSearching(DataSource, dm.Search);
1117+
}
1118+
if (dm.Sorted != null && dm.Sorted.Count > 0)
1119+
{
1120+
// Sorting
1121+
DataSource = DataOperations.PerformSorting(DataSource, dm.Sorted);
1122+
}
1123+
if (dm.Where != null && dm.Where.Count > 0)
1124+
{
1125+
// Filtering
1126+
DataSource = DataOperations.PerformFiltering(DataSource, dm.Where, dm.Where[0].Operator);
1127+
}
1128+
int count = DataSource.Cast<EmployeeDetails>().Count();
1129+
if (dm.Skip != 0)
1130+
{
1131+
//Paging
1132+
DataSource = DataOperations.PerformSkip(DataSource, dm.Skip);
1133+
}
1134+
if (dm.Take != 0)
1135+
{
1136+
DataSource = DataOperations.PerformTake(DataSource, dm.Take);
1137+
}
1138+
return dm.RequiresCounts ? new DataResult() { Result = DataSource, Count = count } : (object)DataSource;
1139+
}
1140+
}
1141+
}
1142+
```
1143+
1144+
### CRUD operation
1145+
1146+
The CRUD operations for the custom bounded data in the diagram component can be implemented by overriding the following CRUD methods of the **DataAdaptor** abstract class,
1147+
1148+
* **Insert/InsertAsync**
1149+
* **Remove/RemoveAsync**
1150+
* **Update/UpdateAsync**
1151+
* **Read/ReadAsync**
1152+
1153+
The following sample code demonstrates implementing CRUD operations for the custom bounded data,
1154+
```cshtml
1155+
@using Syncfusion.Blazor
1156+
@using Syncfusion.Blazor.Diagram
1157+
@using Syncfusion.Blazor.Data
1158+
1159+
@*buttons to perform crud support*@
1160+
<div class="row" style="margin-bottom:20px">
1161+
<div class="col-md-12">
1162+
<div class="row">
1163+
<div class="col-md-3">
1164+
<button class="btn btn-primary" @onclick="Read">Read</button>
1165+
</div>
1166+
<div class="col-md-3">
1167+
<button class="btn btn-primary" @onclick="Update">Update</button>
1168+
</div>
1169+
<div class="col-md-3">
1170+
<button class="btn btn-primary" @onclick="Insert">Insert</button>
1171+
</div>
1172+
<div class="col-md-3">
1173+
<button class="btn btn-primary" @onclick="Delete">Delete</button>
1174+
</div>
1175+
</div>
1176+
</div>
1177+
</div>
1178+
<div class="row" id="diagram">
1179+
<div class="col-md-10">
1180+
<div id="diagram-space" class="content-wrapper">
1181+
<SfDiagramComponent ID="diagramControl" @ref="@diagram" Width="100%" Height="690px" ConnectorCreating="@ConnectorCreating" NodeCreating="@NodeCreating">
1182+
<DataSourceSettings ID="EmployeeID" ParentID="ReportsTo">
1183+
<SfDataManager AdaptorInstance="@typeof(CustomAdaptor)" Adaptor="Adaptors.CustomAdaptor"></SfDataManager>
1184+
</DataSourceSettings>
1185+
<Layout Type="Syncfusion.Blazor.Diagram.LayoutType.HierarchicalTree" VerticalSpacing="75" HorizontalSpacing="75"></Layout>
1186+
</SfDiagramComponent>
1187+
</div>
1188+
</div>
1189+
</div>
1190+
@functions{
1191+
SfDiagramComponent? diagram;
1192+
public static List<EmployeeDetails> employeeDetails { get; set; }
1193+
public static List<EmployeeDetails> Details { get; set; } = new List<EmployeeDetails>();
1194+
1195+
Layout LayoutValue = new Layout() { };
1196+
private TreeInfo GetLayoutInfo(IDiagramObject obj, TreeInfo options)
1197+
{
1198+
options.EnableSubTree = true;
1199+
options.Orientation = Orientation.Horizontal;
1200+
return options;
1201+
}
1202+
private void NodeCreating(IDiagramObject obj)
1203+
{
1204+
Node? node = obj as Node;
1205+
node!.Style = new ShapeStyle() { Fill = "#659be5", StrokeColor = "none", StrokeWidth = 2, };
1206+
node.BackgroundColor = "#659be5";
1207+
node.Width = 200;
1208+
node.Height = 100;
1209+
EmployeeDetails data = node.Data as EmployeeDetails;
1210+
if (data != null)
1211+
{
1212+
//node.ID = data.FirstName + data.EmployeeID;
1213+
node.Annotations = new DiagramObjectCollection<ShapeAnnotation>()
1214+
{
1215+
new ShapeAnnotation()
1216+
{
1217+
ID = data.FirstName,
1218+
Content = $"Name:{data.FirstName}\nReportsTo:{data.ReportsTo}\nDesignation:{data.Designation}\nCountry:{data.Country}",
1219+
Style = new TextStyle(){FontSize = 15, Color = "white"}
1220+
}
1221+
};
1222+
node.Style = new ShapeStyle() { Fill = data.Color, StrokeColor = "none", StrokeWidth = 2, };
1223+
}
1224+
}
1225+
private void ConnectorCreating(IDiagramObject connector)
1226+
{
1227+
Connector? newConnector = connector as Connector;
1228+
newConnector!.TargetDecorator = new DecoratorSettings() { Shape = DecoratorShape.None };
1229+
newConnector.Type = ConnectorSegmentType.Orthogonal;
1230+
newConnector.Style = new ShapeStyle() { StrokeColor = "#6d6d6d" };
1231+
newConnector.Constraints = ConnectorConstraints.None;
1232+
newConnector.CornerRadius = 5;
1233+
}
1234+
1235+
1236+
public class EmployeeDetails
1237+
{
1238+
public string EmployeeID { get; set; }
1239+
1240+
public string ReportsTo { get; set; }
1241+
1242+
public string FirstName { get; set; }
1243+
1244+
public string Designation { get; set; }
1245+
1246+
public string Country { get; set; }
1247+
1248+
public string Color { get; set; }
1249+
}
1250+
1251+
1252+
// Implementing custom adaptor by extending the DataAdaptor class
1253+
public class CustomAdaptor : DataAdaptor
1254+
{
1255+
// Performs data Read operation
1256+
public override object Read(DataManagerRequest dm, string key = null)
1257+
{
1258+
IEnumerable<EmployeeDetails> DataSource = employeeDetails;
1259+
if (dm.Search != null && dm.Search.Count > 0)
1260+
{
1261+
// Searching
1262+
DataSource = DataOperations.PerformSearching(DataSource, dm.Search);
1263+
}
1264+
if (dm.Sorted != null && dm.Sorted.Count > 0)
1265+
{
1266+
// Sorting
1267+
DataSource = DataOperations.PerformSorting(DataSource, dm.Sorted);
1268+
}
1269+
if (dm.Where != null && dm.Where.Count > 0)
1270+
{
1271+
// Filtering
1272+
DataSource = DataOperations.PerformFiltering(DataSource, dm.Where, dm.Where[0].Operator);
1273+
}
1274+
int count = DataSource.Cast<EmployeeDetails>().Count();
1275+
if (dm.Skip != 0)
1276+
{
1277+
//Paging
1278+
DataSource = DataOperations.PerformSkip(DataSource, dm.Skip);
1279+
}
1280+
if (dm.Take != 0)
1281+
{
1282+
DataSource = DataOperations.PerformTake(DataSource, dm.Take);
1283+
}
1284+
return dm.RequiresCounts ? new DataResult() { Result = DataSource, Count = count } : (object)DataSource;
1285+
}
1286+
1287+
// Performs Insert operation
1288+
public override object Insert(DataManager dm, object value, string key)
1289+
{
1290+
employeeDetails.Insert(employeeDetails.Count, value as EmployeeDetails);
1291+
return value;
1292+
}
1293+
1294+
// Performs Remove operation
1295+
public override object Remove(DataManager dm, object value, string keyField, string key)
1296+
{
1297+
employeeDetails.Remove(employeeDetails.Where(or => or.EmployeeID == value.ToString()).FirstOrDefault());
1298+
return value;
1299+
}
1300+
1301+
// Performs Update operation
1302+
public override object Update(DataManager dm, object value, string keyField, string key)
1303+
{
1304+
var data = employeeDetails.Where(or => or.EmployeeID == (value as EmployeeDetails).EmployeeID).FirstOrDefault();
1305+
if (data != null)
1306+
{
1307+
data.EmployeeID = (value as EmployeeDetails).EmployeeID;
1308+
data.ReportsTo = (value as EmployeeDetails).ReportsTo;
1309+
data.FirstName = (value as EmployeeDetails).FirstName;
1310+
data.Designation = (value as EmployeeDetails).Designation;
1311+
data.Country = (value as EmployeeDetails).Country;
1312+
data.Color = (value as EmployeeDetails).Color;
1313+
}
1314+
return value;
1315+
}
1316+
}
1317+
1318+
public void Read()
1319+
{
1320+
Details = new List<EmployeeDetails>();
1321+
Details = diagram.ReadDataAsync().Result as List<EmployeeDetails>;
1322+
}
1323+
1324+
public async void Update()
1325+
{
1326+
EmployeeDetails employeeDetails = new EmployeeDetails { EmployeeID = "1", FirstName = "AndrewSimonds", Designation = "CEO", Country = "Australia", ReportsTo = "", Color = "Red" };
1327+
await diagram.UpdateDataAsync("EmployeeID", employeeDetails);
1328+
}
1329+
1330+
public async void Insert()
1331+
{
1332+
EmployeeDetails employeeDetails = new EmployeeDetails()
1333+
{
1334+
EmployeeID = "10",
1335+
FirstName = "Alan",
1336+
Designation = "HR assistant",
1337+
Country = "USA",
1338+
ReportsTo = "6",
1339+
Color = "Purple"
1340+
};
1341+
await diagram.InsertDataAsync(employeeDetails);
1342+
1343+
}
1344+
1345+
public async void Delete()
1346+
{
1347+
await diagram.DeleteDataAsync("EmployeeID", "6");
1348+
}
1349+
}
1350+
```
1351+
You can download a complete working sample from [GitHub](https://github.com/SyncfusionExamples/Blazor-Diagram-Examples/tree/master/UG-Samples/DataBinding/RemoteData/URLAdaptor)
1352+
10241353
### Binding with GraphQL service
10251354
GraphQL is a query language for APIs with which you can get exactly what you need and nothing more. The GraphQLAdaptor provides an option to retrieve data from the GraphQL server. For more details on GraphQL service, refer to the [GraphQL documentation](../data/adaptors#graphql-service-binding).
10261355

@@ -1339,7 +1668,7 @@ Now, you can configure the diagram using the **'SfDataManager'** to interact wit
13391668
```
13401669

13411670
### CRUD
1342-
The SfDiagramComponent supports CRUD (Create, Read, Update, Delete) operations using SfDataManager for remote data management. By making API calls to update data, the diagram automatically rerenders, ensuring real-time synchronization between the front-end diagram and the backend. This allows users to manage and manipulate diagram data from remote databases or APIs using methods like ReadData, UpdateData, InsertData, and DeleteData.
1671+
The SfDiagramComponent supports CRUD (Create, Read, Update, Delete) operations using SfDataManager for remote data management. By making API calls to update data, the diagram automatically re-renders, ensuring real-time synchronization between the front-end diagram and the back-end. This allows users to manage and manipulate diagram data from remote databases or APIs using methods like ReadData, UpdateData, InsertData, and DeleteData.
13431672

13441673
### Read DataSource
13451674
The SfDiagramComponent can fetch and display data from remote sources using the ReadDataAsync method. This method retrieves data from the server that we visualized as nodes and connectors in the diagram. This method is invoked when the user wants to load the raw data from the server.
@@ -1398,6 +1727,7 @@ The DeleteDataAsync method removes data from the remote server. Once the data is
13981727
```
13991728

14001729
You can find the fully working sample here.
1730+
14011731
## See Also
14021732

14031733
* [How to arrange the diagram nodes and connectors using varies layout](./layout/automatic-layout)

0 commit comments

Comments
 (0)