The requested page is not available for the requested platform. You are viewing the content for Default platform.

Fundamentals

  • 13 min to read

Use Razor syntax to configure DevExtreme ASP.NET MVC controls. The Razor constructions are rendered into the HTML and JavaScript needed to initialize a DevExtreme-based control.

JavaScript Generated from Razor Code

Create a Control

To create a control:

  1. Call the DevExtreme() HtmlHelper extension method.
  2. Call the control's builder method.
@(Html.DevExtreme()
    .Button() // creates the Button control
)

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

@{
    Html.DevExtreme().Button()
        // ...
        // other Button control options go here
        // ...
        .Render()
}

Specify Options

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

Widget Option Control Method
dataSource DataSource
tooltip Tooltip
showColumnHeaders ShowColumnHeaders

Call control methods in a chain (see a fluent interface). In Visual Studio, IntelliSense provides the available method names, their accepted values, and short descriptions.

InstelliSense

Simple Options

To specify an option, call the corresponding control method and pass the option's value.

@(Html.DevExtreme().Button()
    .ID("submitButton") // sets the control container's "ID" attribute
    .Text("submit") // sets the button text
    .Width(100) // sets the button width
)
Note

The ID option is not necessary. However, you should specify it to access the control's JavaScript API at runtime (for example, to call a method).

The ID option's value should meet the following requirements:

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

To specify options that accept a predefined set of values, use .NET enums. Refer to a particular option's description to find out if it accepts an enum.

@(Html.DevExtreme().DateBox()
    .Type(DateBoxType.DateTime) // uses the DateBoxType .NET enum to set the type
)

Nested Options and Collections

You can use lambda expressions to configure nested options. The lambda parameter starts a new chain of methods that specify the nested options.

@(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
        )
    )
)

You can also use lambda expressions to configure options that represent item collections. However, in this case, the lambda parameter performs the role of an item factory. Its Add() method adds a new item to the collection.

@(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);
    })
)

Strongly-Typed Helpers

You can use strongly-typed helpers to configure item collections. 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 Order type. Note that this and the previous codes are equivalent.

@(Html.DevExtreme().DataGrid<Order>()
    .Columns(columns => {
        columns.AddFor(m => m.CustomerID); // uses the `AddFor()` method to configure the columns
        columns.AddFor(m => m.OrderDate);
    })
)

You can also use Strongly-typed helpers to configure 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.

@model ApplicationName.Models.Order

@(Html.DevExtreme().DateBoxFor(m => m.OrderDate))

More examples are available in our demos and sample applications.

Handle Events and Define Callbacks

To handle an event or define a callback, implement a JavaScript function as follows:

  • A short inline function.

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

    @(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>
    
  • A function wrapped into the Razor <text> tag (C# only).

    @(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>)
        )
    )
    

Call Methods

To call methods, use JavaScript as you do to handle events. For example, you have a Popup control:

@(Html.DevExtreme().Popup()
    .ID("popup")
)

This control appears on the page after its show() method is 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...

@* ... *@
@(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 called method accepts arguments, pass them after the method's name. For example, the following code calls the Popup control's toggle(showing) method with true as the argument.

$("#popup").dxPopup("toggle", true);

For more information, see DevExtreme API Reference.

Implement Templates

Templates in DevExtreme-based 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;).

The Razor engine does not parse code within <% %> brackets; you can use only JavaScript within these brackets, since this code is passed to our template engine.

Template Types

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

You can find template examples in our demos and sample applications.

Short Inline Templates

The templates support HTML and ERB-style constructions.

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

Templates with Razor Helpers

The templates also support Razor helpers. 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 you should use an external template for high-level nesting.

@(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>)
)

External Templates

External templates can be declared as a named template or a partial view, or a @helper block. Controls placed in these templates use a special render mechanism. You can declare an external template for high-level nesting or to reuse it.

The following example declares two related templates:

  • The template that contains list items. This template is nested in the List control.
  • The template with the List control. This template is nested in the Popup control.
Named template
@(Html.DevExtreme().Popup()
    .ContentTemplate(new TemplateName("list"))
)
@using (Html.DevExtreme().NamedTemplate("list")) {
    @(Html.DevExtreme().List()
        .ItemTemplate(@<text>
            <div><%= ProductName %></div>
            <div><%= UnitPrice %></div>
        </text>)
    )
}
Note

A named template cannot be defined inside any template.

Partial view
  • InnerList.cshtml

    @(Html.DevExtreme().List()
        .ItemTemplate(@<text>
            <div><%= ProductName %></div>
            <div><%= UnitPrice %></div>
        </text>)
    )
    
  • Popup.cshtml

    @(Html.DevExtreme().Popup()
        .ContentTemplate(@<text>
            @(Html.Partial("InnerList"))
        </text>)
    )
    
@helper
@(Html.DevExtreme().Popup()
    .ContentTemplate(@<text>
        @InnerList()
    </text>)
)  
@helper InnerList() {
    @(Html.DevExtreme().List()
        .ItemTemplate(@<text>
            <div><%= ProductName %></div>
            <div><%= UnitPrice %></div>
        </text>)
    )
}

JavaScript Functions as Templates

To configure DevExtreme ASP.NET MVC controls, you typically use Razor syntax. However, in some cases, you should utilize pure JavaScript with jQuery, for example:

  • to access JavaScript variables;
  • to implement complex logic inside the template.

Short JavaScript functions are declared inline with the method's name (use the new JS() expression).

@(Html.DevExtreme().DataGrid()
    .Columns(columns => {
        columns.Add()
            .CellTemplate(new JS("function (element, cellInfo) { element.addClass('data-grid-custom-cell') }"))
            // ...
    })
)

Multi-line JavaScript functions are declared in an external script, then you can refer to them from the method's name (use the new JS() expression).

@(Html.DevExtreme().List()
    .ItemTemplate(new JS("list_itemTemplate"))
    // ...
)

<script>
    function list_itemTemplate(data, index, element) {
        element.append(
            $("<img />").attr("src", data.imgSrc)
        );
    }
</script>

Access Template Parameters

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

@(Html.DevExtreme().Calendar()
    .CellTemplate(@<text>
        <% if (view !== "month") { %>
            <b><%= text %></b>
        <% } else { %>
            <%= text %>
        <% } %>
    </text>)
)

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

@(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>

The following example shows how to pass a custom parameter:

@(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>
}

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:

@(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>);
    })
)

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:

@(Html.DevExtreme().DataGrid()
    .Columns(columns => {
        columns.Add().CellTemplate(@<text>
            <a href="@Url.Action("ActionName", "ControllerName")/<%= data.id %>">Link Text</a>
        </text>);
    })
)

Master-Detail UI Example

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

@(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>)
    )
)

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 previous 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