Syncfusion EJ2
Essential JS 2 is Syncfusion's current JavaScript component suite. It's modular, written in TypeScript, has no jQuery dependency, and covers everything from grids and charts to a Word-style document editor and a spreadsheet. The Wisej.Web.Ext.Syncfusion2 extension wraps 50 of its components as Wisej.NET controls.

Use this extension for new work. Syncfusion EJ1, the older jQuery-based suite, is kept for existing applications only.
Installation
dotnet add package Wisej-4-Syncfusion2
The package targets .NET Framework 4.8 and .NET 8 or later. After a rebuild, the widgets appear in the Visual Studio toolbox.
Essential JS 2 is a commercial product. You need a Syncfusion licence, which is separate from your Wisej.NET licence. Your Wisej.NET licence must also include the premium extensions. Syncfusion's current releases also check a licence key in the browser, and show a licensing banner without one. Generate the key in your Syncfusion account and set it in the configuration file. The wrapper registers it with ej.base.registerLicense():
{
"source": "cdn",
"theme": "material",
"licenseKey": "YOUR-SYNCFUSION-LICENSE-KEY",
...
}
A key is tied to a Syncfusion version range. When you move the configuration file to a newer Syncfusion release, check that your key covers it.
By default the scripts come from the Syncfusion CDN, version 33.1.44, as the single ej2.min.js bundle plus a theme stylesheet. See Configuration to change the version or serve the files yourself.
How the wrapper works
Every widget derives from ej2Base, which derives from the Wisej.NET Widget. Unlike the other suites, the class names have no prefix. Each class names the EJ2 class it creates, which is also where to look in the EJ2 API reference:
| Wisej.NET class | EJ2 class |
|---|---|
Grid | ej.grids.Grid |
Chart | ej.charts.Chart |
Schedule | ej.schedule.Schedule |
RichTextEditor | ej.richtexteditor.RichTextEditor |
Chat | ej.interactivechat.ChatUI |
The EJ2 properties go into Options, its methods are called through Instance, and its events reach the server as described in Events. The wrapper attaches listeners with EJ2's addEventListener, so use the event names exactly as the EJ2 reference lists them: rowSelected, actionComplete, pointClick.
Menu, TreeView, ListBox, ListView, ProgressBar, DateTimePicker and SplitButton have the same names as classes in Wisej.Web. In VB.NET, which ignores case, so does Toolbar (Wisej.Web.ToolBar). In a file that imports both namespaces, qualify them, as in Wisej.Web.Ext.Syncfusion2.Grid, or add an alias: using ej2 = Wisej.Web.Ext.Syncfusion2;.
Getting started
- C#
- VB.NET
using ej2 = Wisej.Web.Ext.Syncfusion2;
var grid = new ej2.Grid { Dock = DockStyle.Fill };
grid.Options = new
{
dataSource = new[] {
new { OrderID = 10248, CustomerID = "VINET", Freight = 32.38, ShipCountry = "France" },
new { OrderID = 10249, CustomerID = "TOMSP", Freight = 11.61, ShipCountry = "Germany" },
new { OrderID = 10250, CustomerID = "HANAR", Freight = 65.83, ShipCountry = "Brazil" }
},
allowPaging = true,
allowSorting = true,
pageSettings = new { pageSize = 20 },
columns = new object[] {
new { field = "OrderID", headerText = "Order", isPrimaryKey = true, width = 100 },
new { field = "CustomerID", headerText = "Customer" },
new { field = "Freight", format = "C2", textAlign = "Right" },
new { field = "ShipCountry", headerText = "Country" }
}
};
// https://ej2.syncfusion.com/documentation/api/grid/#rowselected
grid.Instance.onRowSelected += new WidgetEventHandler((s, e) =>
{
AlertBox.Show("Selected order " + e.Data.data.OrderID);
});
this.Controls.Add(grid);
Option Strict Off
Imports ej2 = Wisej.Web.Ext.Syncfusion2
Dim grid As New ej2.Grid With {.Dock = DockStyle.Fill}
grid.Options = New With {
.dataSource = {
New With {.OrderID = 10248, .CustomerID = "VINET", .Freight = 32.38, .ShipCountry = "France"},
New With {.OrderID = 10249, .CustomerID = "TOMSP", .Freight = 11.61, .ShipCountry = "Germany"},
New With {.OrderID = 10250, .CustomerID = "HANAR", .Freight = 65.83, .ShipCountry = "Brazil"}
},
.allowPaging = True,
.allowSorting = True,
.pageSettings = New With {.pageSize = 20},
.columns = New Object() {
New With {.field = "OrderID", .headerText = "Order", .isPrimaryKey = True, .width = 100},
New With {.field = "CustomerID", .headerText = "Customer"},
New With {.field = "Freight", .format = "C2", .textAlign = "Right"},
New With {.field = "ShipCountry", .headerText = "Country"}
}
}
grid.AddListener("rowSelected", AddressOf Grid_RowSelected)
Me.Controls.Add(grid)
Private Sub Grid_RowSelected(sender As Object, e As WidgetEventArgs)
AlertBox.Show("Selected order " & e.Data.data.OrderID)
End Sub
Calling a method works the same way:
// https://ej2.syncfusion.com/documentation/api/grid/#excelexport
// (requires allowExcelExport = true in the options)
this.grid1.Instance.excelExport();
// Methods that return data have an Async version.
var records = await this.grid1.Instance.getSelectedRecordsAsync();
EJ2 column, row and item templates can refer to a <script> block by id, as in template = "#statusTemplate". Register those blocks with the WidgetTemplates property. See Templates. For templates that need logic, use a widget function and the "()=>myTemplate" option syntax.
Widgets
| Area | Classes |
|---|---|
| Data | Grid, TreeGrid, PivotView, QueryBuilder, ListBox, ListView, TreeView, Kanban |
| Charts and gauges | Chart, AccumulationChart, StockChart, BulletChart, SmithChart, Sparkline, RangeNavigator, HeatMap, TreeMap, Maps, CircularGauge, LinearGauge |
| Scheduling | Schedule, Gantt, Calendar |
| Documents | DocumentEditor, Spreadsheet, PDFViewer, RichTextEditor, Diagram, SymbolPalette, FileManager, Uploader, Signature |
| Editors | DatePicker, DateRangePicker, DateTimePicker, TimePicker, DropDownList, DropDownTree, MultiSelect, ColorPicker, Slider, InPlaceEditor, ChipList |
| Navigation and layout | Menu, Toolbar, Sidebar, SplitButton, ProgressButton, ProgressBar |
| Conversation | Chat |
DocumentEditor, Spreadsheet and PDFViewer can also call Syncfusion's server-side web services, for example to open .docx files or to render PDF pages. Those services aren't part of the extension: host them yourself and set their URLs in the options, following the Syncfusion documentation.
The Chat widget
Chat is the one class with a typed .NET API on top of the EJ2 options. It wraps ej.interactivechat.ChatUI with:
- Properties for the common settings, including
User,Messages,Suggestions,Placeholder,HeaderText,ShowHeader,ShowFooter,ShowTimeStamp,TimeStampFormat,TypingUsers,MentionUsers,EnableAttachmentsandAttachmentSettings, plus template properties (MessageTemplate,EmptyChatTemplate, …). - Methods:
AddMessage,AddMessageAsync,UpdateMessage,RemoveMessage,ClearMessages,ScrollToBottom,ScrollToTop,ScrollToMessage,FocusInputandRefreshChat. - Events with typed arguments:
MessageSend,UserTyping,MentionSelect,SuggestionClick,HeaderToolbarItemClicked,MessageToolbarItemClicked, and the attachment eventsAttachmentClick,BeforeAttachmentUpload,AttachmentUploadSuccess,AttachmentUploadFailureandAttachmentRemoved.
The model classes, Chat.ChatUser, Chat.ChatMessage and the rest, are nested in Chat.
- C#
- VB.NET
var me = new ej2.Chat.ChatUser { Id = "u1", User = "Jane" };
var bot = new ej2.Chat.ChatUser { Id = "bot", User = "Assistant" };
this.chat1.User = me;
this.chat1.HeaderText = "Support";
this.chat1.Suggestions = new[] { "Track my order", "Talk to a person" };
this.chat1.MessageSend += (s, e) =>
{
var question = e.Message.Text;
this.chat1.AddMessage(new ej2.Chat.ChatMessage
{
Author = bot,
Text = "You asked: " + question,
TimeStamp = DateTime.Now
});
};
Dim [me] As New ej2.Chat.ChatUser With {.Id = "u1", .User = "Jane"}
Dim bot As New ej2.Chat.ChatUser With {.Id = "bot", .User = "Assistant"}
Me.Chat1.User = [me]
Me.Chat1.HeaderText = "Support"
Me.Chat1.Suggestions = {"Track my order", "Talk to a person"}
AddHandler Me.Chat1.MessageSend,
Sub(s, e)
Me.Chat1.AddMessage(New ej2.Chat.ChatMessage With {
.Author = bot,
.Text = "You asked: " & e.Message.Text,
.TimeStamp = DateTime.Now
})
End Sub
The RichTextEditor class also adds a typed Text property that holds the editor's content.
Themes and localization
ej2Base.Theme selects the EJ2 theme for the session. The value is the name of a stylesheet at the root of the EJ2 distribution, such as material, material3, bootstrap5, fluent2, tailwind or fabric, with a -dark variant for most. ej2Base.Culture changes the culture of the EJ2 components: the wrapper calls ej.base.setCulture() and re-creates the widgets. EJ2 needs its CLDR culture data and localized texts for cultures other than en-US. Load them as extra packages in the configuration file.
ej2Base.Theme = "fluent2";
ej2Base.Culture = new CultureInfo("de-DE");
Resources
- Essential JS 2 documentation
- API reference
- Demos
- Licensing and licence keys
- Premium extensions overview: options, methods, events, functions and templates
- Configuration: versions, sources, licence key, themes