DevExtreme jQuery - Fundamentals

DevExtreme ASP.NET MVC Controls are a set of server-side controls that allow you to configure JavaScript-based DevExtreme widgets using familiar Razor syntax. The Razor constructions are rendered into the HTML and JavaScript needed to initialize a DevExtreme widget.

DevExtreme ASP.NET MVC Controls - JavaScript Generated from Razor Code

This guide offers the basics in DevExtreme ASP.NET MVC Controls, such as creating and configuring a control, handling the events and implementing templates.

See Also

Creating a Control

To create a control, start with calling the DevExtreme() HtmlHelper extension method. Then, call the builder method corresponding to the control you want to create.

Razor C#
Razor VB
@(Html.DevExtreme()
    .Button() // creates the Button control
)
@(Html.DevExtreme() _
    .Button() ' creates the Button control
)

If you are creating a control inside a code block, end the configuration with a call of the Render() method.

Razor C#
Razor VB
@{
    Html.DevExtreme().Button()
        // ...
        // other options of the Button control go here
        // ...
        .Render()
}
@Code
    Html.DevExtreme().Button() _
        @* ...
           other options of the Button control go here
           ... *@
        .Render()
End Code

Specifying the Options

DevExtreme ASP.NET MVC Controls mirror the client-side widget options with only one difference: instead of the lower camel case usual in JavaScript, control methods use the upper camel case common in .NET, for example:

Widget Option Control Method
dataSource DataSource
tooltip Tooltip
showColumnHeaders ShowColumnHeaders

Control methods are called using a fluent interface. In Visual Studio, IntelliSense prompts you the available method names, their accepted values, and short descriptions.

DevExtreme ASP.NET MVC Controls - InstelliSense

Simple Options

To specify a simple option, call the corresponding control method and pass the required option value.

Razor C#
Razor VB
@(Html.DevExtreme().Button()
    .ID("submitButton") // sets the "id" attribute of the control container
    .Text("submit") // sets the button text
    .Width(100) // sets the button width
)
@(Html.DevExtreme().Button() _
    .ID("submitButton") _
    .Text("submit") _
    .Width(100)
)
NOTE

Specifying the ID option is not necessary. However, you may need it if you plan to access the control's JavaScript API at runtime (for example, to call a method). The ID option's value should meet certain requirements:

  • It must always be unique in a page's context;
  • If a partial view is loaded multiple times, each partial view instance must render all the controls with unique IDs;
  • It should meet the id attribute's requirements in HTML5.

Options that accept a predefined set of values are specified using .NET enums. Refer to a particular option's description to learn if it accepts a enum.

Razor C#
Razor VB
@(Html.DevExtreme().DateBox()
    .Type(DateBoxType.DateTime) // sets the type using the DateBoxType .NET enum
)
@(Html.DevExtreme().DateBox() _
    .Type(DateBoxType.DateTime) ' sets the type using the DateBoxType .NET enum
)

Nested Options and Collections

Nested options are configured using lambda expressions. The lambda parameter starts a new chain of methods that specify the nested options.

Razor C#
Razor VB
@(Html.DevExtreme().Chart()
    .Legend(l => l // configures the chart legend (l - lambda parameter)
        .Visible(false) // hides the legend in the chart
    )
    .Tooltip(t => t // configures the tooltip (t - lambda parameter)
        .Enabled(true) // enables the tooltip
        .Font(f => f // configures the tooltip's text (f - lambda parameter)
            .Color("blue") // paints the tooltip's text in blue
        )
    )
)
@(Html.DevExtreme().Chart() _
    .Legend(Sub(l)
        l.Visible(False)
    End Sub) _
    .Tooltip(Sub(t)
        t.Enabled(True) _
         .Font(Sub(f)
             f.Color("blue")
         End Sub)
    End Sub)
)

Options that represent item collections are configured using lambda expressions as well, but in this case, the lambda parameter performs the role of an item factory. Its Add() method adds a new item to the collection.

Razor C#
Razor VB
@(Html.DevExtreme().DataGrid()
    .Columns(columns => { // specifies a collection of columns
        columns.Add() // adds the "CustomerID" column
            .DataField("CustomerID");

        columns.Add() // adds the "OrderDate" column
            .DataField("OrderDate")
            .DataType(GridColumnDataType.Date);
    })
)
@(Html.DevExtreme().DataGrid() _
    .Columns(Sub(columns)
        columns.Add() _
            .DataField("CustomerID")

        columns.Add() _
            .DataField("OrderDate") _
            .DataType(GridColumnDataType.Date)
    End Sub)
)

Strongly-Typed Helpers

Many item collections can be configured using strongly-typed helpers. This approach automatically adds client-side validation based on Data Annotations, ensures compile-time type safety, and enables IntelliSense. In the following code, the DataGrid is strongly-typed to the type Order, and the columns are configured using the AddFor() method. Note that this and the previous codes are equivalent.

Razor C#
Razor VB
@(Html.DevExtreme().DataGrid<Order>()
    .Columns(columns => {
        columns.AddFor(m => m.CustomerID);
        columns.AddFor(m => m.OrderDate);
    })
)
@(Html.DevExtreme().DataGrid(Of Order)() _
    .Columns(Sub(columns)
        columns.AddFor(Function(m) m.CustomerID)
        columns.AddFor(Function(m) m.OrderDate)
    End Sub)
)

Strongly-typed helpers can also be used for configuring standalone editors. Methods that create the editors end with For. For example, the DateBoxFor() method creates the DateBox control. Browse IntelliSense suggestions for a full list of available strongly-typed helpers.

Razor C#
Razor VB
@model ApplicationName.Models.Order

@(Html.DevExtreme().DateBoxFor(m => m.OrderDate))
@ModelType ApplicationName.Models.Order

@(Html.DevExtreme().DateBoxFor(Function(m) m.OrderDate))

More examples are available in our technical demos and sample applications.

Handling Events and Defining Callbacks

Event handlers and callbacks are defined by JavaScript functions which can be specified in the following manners.

  • A short inline function.

    Razor C#
    Razor VB
    @(Html.DevExtreme().Button()
        .OnClick("function () { alert('The button was clicked'); }")
    )
    
    @(Html.DevExtreme().VectorMap()
        .Tooltip(t => t
            .CustomizeTooltip("function (arg) { return { text: arg.attribute('text') } }")
        )
    )
    @(Html.DevExtreme().Button() _
        .OnClick("function () { alert('The button was clicked'); }")
    )
    
    @(Html.DevExtreme().VectorMap() _
        .Tooltip(Sub(t)
            t.CustomizeTooltip("function (arg) { return { text: arg.attribute('text') } }")
        End Sub)
    )
  • An external function.

    Razor C#
    Razor VB
    @(Html.DevExtreme().Button()
        .OnClick("myButton_click")
    )
    
    @(Html.DevExtreme().VectorMap()
        .Tooltip(t => t
            .CustomizeTooltip("vectorMap_tooltip_customizeTooltip")
        )
    )
    
    <script>
        function myButton_click() {
            alert("The button was clicked");
        }
        function vectorMap_tooltip_customizeTooltip (arg) {
            return { text: arg.attribute("text") };
        }
    </script>
    @(Html.DevExtreme().Button() _
        .OnClick("myButton_click")
    )
    
    @(Html.DevExtreme().VectorMap() _
        .Tooltip(Sub(t)
            t.CustomizeTooltip("vectorMap_tooltip_customizeTooltip")
        End Sub)
    )
    
    <script>
        function myButton_click() {
            alert("The button was clicked");
        }
        function vectorMap_tooltip_customizeTooltip (arg) {
            return { text: arg.attribute("text") };
        }
    </script>
  • A function wrapped into the Razor <text> tag (C# only).

    Razor C#
    @(Html.DevExtreme().Button()
        .OnClick(@<text>
            function () {
                alert("The button was clicked");
            }
        </text>)
    )
    
    @(Html.DevExtreme().VectorMap()
        .Tooltip(t => t
            .CustomizeTooltip(@<text>
                function (arg) {
                    return { text: arg.attribute("text") };
                }
            </text>)
        )
    )

Calling Methods

To call methods, use JavaScript, much like you did to handle events. For instance, let's say you have a Popup control.

Razor C#
Razor VB
@(Html.DevExtreme().Popup()
    .ID("popup")
)
@(Html.DevExtreme().Popup() _
    .ID("popup")
)

This control appears on the page only after its show() method was called. The following code demonstrates how to call this method.

$("#popup").dxPopup("show");

You can put this code in any JavaScript constructions and execute it whenever you need to, for example, when a user clicks a button...

Razor C#
Razor VB
@* ... *@
@(Html.DevExtreme().Button()
    .OnClick("showPopup")
)
<script>
    function showPopup() {
        $("#popup").dxPopup("show");
    }
</script>
@* ... *@
@(Html.DevExtreme().Button() _
    .OnClick("showPopup")
)
<script>
    function showPopup() {
        $("#popup").dxPopup("show");
    }
</script>

... or once your page is ready.

// ...
<script>
    $(showPopup);

    function showPopup() {
        $("#popup").dxPopup("show");
    }
</script>

If the method you are calling accepts arguments, pass them after the method's name. For example, the following code calls the toggle(showing) method of the Popup control with true as an argument.

$("#popup").dxPopup("toggle", true);
See Also
  • API Reference.ControlName.Methods, for example, API Reference.Popup.Methods - lists all methods of a specific control.

Implementing Templates

Templates in DevExtreme ASP.NET MVC Controls support ERB-style syntax. The following constructions are available.

  • <% code %> - executes the code.
  • <%= value %> - prints the value as is (for example, <b>John</b>).
  • <%- value %> - prints the value escaping HTML (<b>John</b> becomes &lt;b&gt;John&lt;/b&gt;).

There are four ways to declare templates in DevExtreme ASP.NET MVC Controls.

Short Inline Templates

These templates support HTML and ERB-style constructions.

Razor C#
Razor VB
@(Html.DevExtreme().Popup()
    .TitleTemplate("<b>Title</b>")
)
@(Html.DevExtreme().Popup() _
    .TitleTemplate("<b>Title</b>")
)
Razor C#
Razor VB
@(Html.DevExtreme().List()
    .ItemTemplate("<div><%= ProductName %></div>")
)
@(Html.DevExtreme().List() _
    .ItemTemplate("<div><%= ProductName %></div>")
)

Templates with Razor Helpers

Apart from HTML and ERB-style constructions, these templates support Razor helpers. Frequently, such templates are used to nest one control in another. For example, the following code nests the DataGrid control in the Popup control. Note that for high-level nesting, you need to use an external template (see below).

Razor C#
Razor VB
@(Html.DevExtreme().Popup()
    // ...
    // Specifies the contents of the Popup control
    .ContentTemplate(@<text>
        @(Html.DevExtreme().DataGrid()
            .DataSource(d => d.WebApi().Controller("GridData"))
            .Columns(columns => {
                columns.Add().DataField("DataField1");
                columns.Add().DataField("DataField2");
                columns.Add().DataField("DataField3");
                columns.Add().DataField("DataField4");
            })
        )
    </text>)
)
@Code ' Wrap the widget in Code if you use @<text> inside
    Html.DevExtreme().Popup() _
        .ContentTemplate(Sub()
            @<text>
                @(Html.DevExtreme().DataGrid() _
                    .DataSource(Function(d) d.WebApi().Controller("GridData")) _
                    .Columns(Sub(columns)
                        columns.Add().DataField("DataField1")
                        columns.Add().DataField("DataField2")
                        columns.Add().DataField("DataField3")
                        columns.Add().DataField("DataField4")
                    End Sub)
                )
            </text>
        End Sub) _
        .Render() ' End the configuration with Render() because it is inside Code
End Code

External Templates

External templates can be declared as a named template, a partial view, or a @helper block (MVC 5 only). Controls placed in such a template use a special rendering mechanism. Usually, you should declare an external template for high-level nesting or if you want to reuse it. In the following example, a template containing list items is nested in the List control, and a template with the List control is nested in the Popup control:

  • Named template

    Razor C#
    Razor VB
    @(Html.DevExtreme().Popup()
        .ContentTemplate(new TemplateName("list"))
    )
    @using (Html.DevExtreme().NamedTemplate("list")) {
        @(Html.DevExtreme().List()
            .ItemTemplate(@<text>
                <div><%= ProductName %></div>
                <div><%= UnitPrice %></div>
            </text>)
        )
    }
    @Code
        Html.DevExtreme().Popup() _
            .ContentTemplate(New TemplateName("list")).Render()
    End Code
    @Using (Html.DevExtreme().NamedTemplate("list"))
        @Code
            Html.DevExtreme().List() _
                .ItemTemplate(Sub()
                    @<text>
                        <div><%= ProductName %></div>
                        <div><%= UnitPrice %></div>
                    </text>
                End Sub).Render()
        End Code
    End Using
    NOTE
    A named template cannot be defined inside any template.
  • Partial view

    • InnerList.cshtml / InnerList.vbhtml

      Razor C#
      Razor VB
      @(Html.DevExtreme().List()
          .ItemTemplate(@<text>
              <div><%= ProductName %></div>
              <div><%= UnitPrice %></div>
          </text>)
      )
      @Code
          Html.DevExtreme().List() _
              .ItemTemplate(Sub()
                  @<text>
                      <div><%= ProductName %></div>
                      <div><%= UnitPrice %></div>
                  </text>
              End Sub).Render()
      End Code
    • Popup.cshtml / Popup.vbhtml

      Razor C#
      Razor VB
      @(Html.DevExtreme().Popup()
          .ContentTemplate(@<text>
              @(Html.Partial("InnerList"))
          </text>)
      )
      @Code
          Html.DevExtreme().Popup() _
              .ContentTemplate(Sub()
                  @<text>
                      @(Html.Partial("InnerList"))
                  </text>
              End Sub).Render()
      End Code
  • @helper (MVC 5 only)

    Razor C#
    Razor VB
    @(Html.DevExtreme().Popup()
        .ContentTemplate(@<text>
            @InnerList()
        </text>)
    )  
    @helper InnerList() {
        @(Html.DevExtreme().List()
            .ItemTemplate(@<text>
                <div><%= ProductName %></div>
                <div><%= UnitPrice %></div>
            </text>)
        )
    }
    @Code
        Html.DevExtreme().Popup() _
            .ContentTemplate(Sub()
                @InnerList()
            End Sub).Render()
    End Code
    @helper InnerList()
        @(Html.DevExtreme().List() _
            .ItemTemplate(Sub()
                Write(ListItem())
            End Sub)
        )
    End Helper
    @helper ListItem()
        @<text>
            <div><%= ProductName %></div>
            <div><%= UnitPrice %></div>
        </text>
    End Helper

Accessing Template Parameters

Templates have parameters that provide access to related data. They correspond to the *Data or *Info object's fields that are listed in the template's API reference description. For example, the Calendar's СellTemplate provides the itemData object. It contains three fields: date, view, and text, that can be used in the template:

Razor C#
Razor VB
@(Html.DevExtreme().Calendar()
    .CellTemplate(@<text>
        <% if (view !== "month") { %>
            <b><%= text %></b>
        <% } else { %>
            <%= text %>
        <% } %>
    </text>)
)
@Code
    Html.DevExtreme().Calendar() _
        .CellTemplate(Sub()
            @<text>
                <% if (view !== "month") { %>
                    <b><%= text %></b>
                <% } else { %>
                    <%= text %>
                <% } %>
            </text>
        End Sub).Render()
End Code

Template parameters can be passed to an external JavaScript function like the data parameter in the following code. This parameter belongs to the cellInfo object described in the DataGrid column's CellTemplate article:

Razor C#
Razor VB
@(Html.DevExtreme().DataGrid()
    // ...
    .Columns(cols => {
        // ...
        cols.Add().CellTemplate(@<text>
            @(Html.DevExtreme().Button()
                .Text("Log Data")
                .OnClick("function () { log(data); }")
            )
        </text>);
    })
)

<script type="text/javascript">
    function log(value) {
        console.log(value);
    }
</script>
@Code
    Html.DevExtreme().DataGrid() _
        // ...
        .Columns(Sub(cols)
            // ...
            cols.Add().CellTemplate(Sub()
                @<text>
                    @(Html.DevExtreme().Button() _
                        .Text("Log Data") _
                        .OnClick("function () { log(data); }")
                    )
                </text>
            End Sub)
        End Sub).Render()
End Code

<script type="text/javascript">
    function log(value) {
        console.log(value);
    }
</script>

In the previous examples, the control passes parameters to the template. The following example shows how you can pass a custom parameter:

Razor C#
Razor VB
@(Html.DevExtreme().TabPanel()
    .Items(items => {
        items.Add()
            .Title("Tab 1")
            .Option("customParams", new { param1 = "value1" })
            .Template(new TemplateName("tab1Content"));
    })
)

@using (Html.DevExtreme().NamedTemplate("tab1Content")) {
    <div><%= customParams.param1 %></div>
}
@Code
    Html.DevExtreme().TabPanel() _
        .Items(Sub(items)
            items.Add() _
                .Title("Tab 1") _
                .Option("customParams", New With { .param1 = "value1" }) _
                .Template(New TemplateName("tab1Content"))
        End Sub).Render()
End Code

@Using (Html.DevExtreme().NamedTemplate("tab1Content"))
    @<text>
        <div><%= customParams.param1 %></div>
    </text>
End Using

HTML Helpers in Templates

You can use HTML helpers in templates as usual if they render static content.

If the content is dynamic and you need to access template parameters, apply the following solution:

Razor C#
Razor VB
@(Html.DevExtreme().DataGrid()
    .Columns(columns => {
        columns.Add().CellTemplate(@<text>
            @Html.Raw(
                Html.ActionLink("Link Text", "ActionName", "ControllerName", new { id = "ID_PLACEHOLDER" }, null)
                    .ToString()
                    .Replace("ID_PLACEHOLDER", "<%= data.id %>")
            )
        </text>);
    })
)
@Code
    Html.DevExtreme().DataGrid() _
        .Columns(Sub(columns)
            columns.Add().CellTemplate(Sub()
                @<text>
                    @Html.Raw(
                        Html.ActionLink("Link Text", "ActionName", "ControllerName", New With {.id = "ID_PLACEHOLDER"}, Nothing) _
                            .ToString() _
                            .Replace("ID_PLACEHOLDER", "<%= data.id %>")
                    )
                </text>
            End Sub)
        End Sub) _
        .Render()
End Code

In this code, the ActionLink has a dynamic route value (id) the data.ID template parameter should provide. However, you should use a placeholder because data.ID cannot be passed to id (the ActionLink is generated on the server and data.ID receives a value only on the client).

You can use HTML elements instead of helpers because HTML helpers only render HTML elements on the page:

Razor C#
Razor VB
@(Html.DevExtreme().DataGrid()
    .Columns(columns => {
        columns.Add().CellTemplate(@<text>
            <a href="@Url.Action("ActionName", "ControllerName")/<%= data.id %>">Link Text</a>
        </text>);
    })
)
@Code
    Html.DevExtreme().DataGrid() _
        .Columns(Sub(columns)
            columns.Add().CellTemplate(Sub()
                @<text>
                    <a href="@Url.Action("ActionName", "ControllerName")/<%= data.id %>">Link Text</a>
                </text>
            End Sub)
        End Sub) _
        .Render()
End Code

JavaScript Functions as Templates

Despite being a superstructure over JavaScript widgets, controls get the best from Razor syntax, but still, in some cases, Razor appears to be short of certain capabilities. In these cases, we recommend you utilize pure JavaScript backed with jQuery. Regarding templates, prefer the JavaScript function over the Razor block when you need to access JavaScript variables or implement sophisticated logic inside the template.

Short JavaScript functions can be declared inline with the method's name using the new JS() expression.

Razor C#
Razor VB
@(Html.DevExtreme().DataGrid()
    .Columns(columns => {
        columns.Add()
            .CellTemplate(new JS("function (element, cellInfo) { element.addClass('data-grid-custom-cell') }"))
            // ...
    })
)
@(Html.DevExtreme().DataGrid() _
    .Columns(Sub(columns)
        columns.Add() _
            .CellTemplate(New JS("function (element, cellInfo) { element.addClass('data-grid-custom-cell') }")) _
            ' ...
    End Sub)
)

Multi-line JavaScript functions should be declared in an external script and then referred to from the method's name using the same new JS() expression.

Razor C#
Razor VB
@(Html.DevExtreme().List()
    .ItemTemplate(new JS("list_itemTemplate"))
    // ...
)
@(Html.DevExtreme().List() _
    .ItemTemplate(New JS("list_itemTemplate"))
    ' ...
)
<script>
    function list_itemTemplate(data, index, element) {
        element.append(
            $("<img />").attr("src", data.imgSrc)
        );
    }
</script>

Master-Detail UI Example

A common use case of templates is the detail section of the master-detail UI in the DataGrid control. Consider the following code, in which the detail section nests another DataGrid whose controller gets the data.OrderID free variable as a loading parameter.

Razor C#
Razor VB
@(Html.DevExtreme().DataGrid()
    .DataSource(d => d.WebApi().Controller("DataGridMasterDetailView").Key("ID"))
    .Columns(columns => {
        columns.Add().DataField("FirstName");
        columns.Add().DataField("LastName");
        // ...
    })
    // Configures the master-detail UI
    .MasterDetail(md => md
        .Enabled(true)
        // Specifies the contents of the detail section
        .Template(@<text>
            @(Html.DevExtreme().DataGrid()
                .DataSource(d => d.WebApi()
                    .Controller("DataGridMasterDetailView")
                    .LoadAction("TasksDetails")
                    // Passes "ID" as a parameter to "DataGridMasterDetailViewController"
                    .LoadParams(new { id = new JS("data.ID") })
                )
            )
        </text>)
    )
)
@Code ' Wrap the widget in Code if you use @<text> inside
    Html.DevExtreme().DataGrid() _
        .DataSource(Function(d) d.WebApi().Controller("DataGridMasterDetailView").Key("ID")) _
        .Columns(Sub(columns)
            columns.Add().DataField("FirstName")
            columns.Add().DataField("LastName")
            ' ...
        End Sub) _
        .MasterDetail(Sub(md)
            ' Configures the master-detail UI
            md.Enabled(True) _
            .Template(Sub()
                    @<text>
                        @(Html.DevExtreme().DataGrid() _
                            .DataSource(Function(d)
                                Return d.WebApi() _
                                        .Controller("DataGridMasterDetailView") _
                                        .LoadAction("TasksDetails") _
                                        .LoadParams(New With { .id = New JS("data.ID") }) ' Passes "ID" as a parameter
                                                                                        ' to "DataGridMasterDetailViewController"
                            End Function)
                        )
                    </text>
            End Sub)
        End Sub) _
        .Render()  ' End the configuration with Render() because it is inside Code
End Code

Note that the data.ID free variable is wrapped in the new JS() construction. This construction allows you to embed JavaScript statements in the resulting control configuration. In particular, the data source configuration of the nested DataGrid from the preceding code yields the following output.

"dataSource": {
    "store": DevExpress.data.AspNet.createStore({
        "loadParams": {
            "orderID": data.ID
        },
        "loadUrl": "/api/DataGridMasterDetailView/TasksDetails",
        "insertUrl": "/api/DataGridMasterDetailView/Post",
        "updateUrl": "/api/DataGridMasterDetailView/Put",
        "deleteUrl": "/api/DataGridMasterDetailView/Delete"
    })
}

View Demo

You can find more examples of templates in our technical demos and sample applications.