Add Widget to MVC Project

DevExtreme widgets are HTML/JavaScript widgets. They can be easily added to any web application/site. In this tutorial, you will see how to add a widget to an MVC project.

See Also
Download Code

Prepare a Sample Application

Open Visual Studio and create a new MVC application project using an empty ASP.NET MVC Web Application template.

To use DevExtreme widgets in MVC applications, add scripts and themes supplied with the DevExtreme Web kit. For this purpose, use the DevExtreme Web NuGet package.

  1. Right-click your project in the Solution Explorer window and choose Manage NuGet Packages... in the context menu.

    NuGetVS

  2. Choose Online in the right column of the appeared window.

    NuGetVS

    Make sure that you have nuget.org as your online source. Then, type DevExtreme Web within the Search Online text box.

  3. When the search is complete, click the Install button of the found item.

    NuGetVS

After the successful install of the DevExtreme Web NuGet package, you will find the following scripts added to your project.

DevExtreme Scripts

  • jQuery version 1.11.2 (you can add jQuery version 2.1.3 if you do not need to support IE 8)
  • Globalize
  • ChartJS (the Data Visualization Widgets library)
  • WebAppJS (the DevExtreme Web total library)
  • DevExtreme Modules (scripts defining different parts of DevExtreme widgets)
  • DevExtreme Localization (files with predefined localization)

In addition, the Content folder will be populated by the following files.

DevExtreme Content

As you can see in the image above, all the predefined DevExtreme themes are added. You can leave only those that you will really use. The layouts folder includes Web-specific layouts that can be used in an application built using the DevExtreme SPA framework. As you are going to build an MVC application, remove this folder from the project.

Add a Home controller and an Index view to your project. Within the view, add links to the jQuery, Globalize and WebAppJS scripts. Note that in addition to these script libraries, each DevExtreme widget requires two stylesheet files. The dx.common.css stylesheet provides the core styles. This stylesheet is required regardless of the target platform and theme. The second stylesheet is a theme-file that provides the distinctive look of the widget.

HTML
<html>
    <head runat="server">
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
        <link rel="stylesheet" type="text/css" href="/Content/dx.common.css" />
        <link rel="stylesheet" type="text/css" href="/Content/dx.light.css" />
        <script src="/Scripts/jquery-1.11.1.min.js"></script>
        <script src="/Scripts/globalize/globalize.js"></script>
        <script src="/Scripts/dx.webappjs.js"></script>
    </head>
    <body>
        <div>

        </div>
    </body>
</html>

NOTE: Add references to script libraries exactly in the same order as presented in the code above.

Run the project to check that it works. An empty page with the "Index" title will load.

See Also

Add a DevExtreme Widget

All DevExtreme widgets are added to web applications in the same manner. You will create a dxButton widget to understand the common principles of adding widgets. In addition, you will learn how to handle widget events and modify widget configuration at runtime.

There are three possible approaches to add DevExtreme widgets: jQuery, Knockout and AngularJS. Each of these approaches will be demonstrated below.

jQuery Approach

Add a Button Widget

To create a button widget, add a div element with the id attribute set to "buttonContainer" to the body of your view, as shown in the code below.

HTML
<html>
    <!--...-->
    <body>
        <div id="buttonContainer"></div>
    </body>
</html>

To associate the dxButton widget with the created element, the dxButton constructor must be called once the document has been loaded. So, add a JavaScript file to your project to provide code behind the view. Link this file within the view.

HTML
<html>
    <head runat="server">
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
        <link rel="stylesheet" type="text/css" href="/Content/dx.common.css" />
        <link rel="stylesheet" type="text/css" href="/Content/dx.light.css" />
        <script src="/Scripts/jquery-1.11.1.min.js"></script>
        <script src="/Scripts/globalize/globalize.js"></script>
        <script src="/Scripts/dx.webappjs.js"></script>
        <script src="/MyJS/script_jQuery.js"></script>
    </head>
    <body>
        <div id="buttonContainer"></div>
    </body>
</html>

Here is the code demonstrating how to call the dxButton constructor.

JavaScript
$(function () {
    $("#buttonContainer").dxButton({
        text: "Generate random value"
    });
});

As you can see in this code, a configuration object must be passed to specify configuration options for the widget. Here, the configuration object contains only the text option, which specifies the button text.

Handle Click Event

To handle a button click, assign a handling function to the onClick option of the widget.

In the code below, the handling function generates a string consisting of ten random digits and displays it within the <p> element specially added to the HTML document.

HTML
<body>
    <div id="buttonContainer"></div>
    <p id="randomValue">0000000000</p>
</body>
JavaScript
$(function () {
    $("#buttonContainer").dxButton({
        text: "Generate random value",
        onClick: function () {
            var result = "";
            for (var i = 0; i < 10; i++)
                result += Math.round(Math.random() * 9);
            $("#randomValue").text(result);
        }
    });
});

Modify Option Value at Runtime

To change enabled state of the button, add the dxCheckBox widget. When changing the check box value, the button will be enabled/disabled at runtime.

Add the dxCheckBox widget in the same manner as you added the dxButton widget. To handle check box value changes, implement the appropriate function and assign it to the onValueChanged option of the dxCheckBox widget. In this function, access the button widget by calling the dxButton function of the button element and by passing "instance" as a parameter. To change a configuration option of the accessed button, call the option method passing the following arguments.

  • "disabled"
    Pass the name of the option to update.
  • actionOptions.value
    Pass the new option value. To get the current checkbox value, use the value field of the object passed as a parameter to the onValueChanged handling function.
HTML
<body>
    <div id="buttonContainer"></div>
    <p id="randomValue">0000000000</p>
    <p>Disable button <span id="checkBoxContainer"></span></p>
</body>
JavaScript
$(function () {
    $("#buttonContainer").dxButton({
        text: "Generate random value",
        onClick: function () {
            var result = "";
            for (var i = 0; i < 10; i++)
                result += Math.round(Math.random() * 9);
            $("#randomValue").text(result);
        }
    });
    $("#checkBoxContainer").dxCheckBox({
        value: false,
        onValueChanged: function (actionOptions) {
            var button = $("#buttonContainer").dxButton("instance");
            button.option("disabled", actionOptions.value);
        }
    });
});

Knockout Approach

To use the Knockout approach, add the knockout-3.4.0.js script library to the Scripts folder of your project. You can find this library in your DevExtreme package.

Reference the Knockout library in the Index view.

HTML
<head runat="server">
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <link rel="stylesheet" type="text/css" href="/Content/dx.common.css" />
    <link rel="stylesheet" type="text/css" href="/Content/dx.light.css" />
    <script src="/Scripts/jquery-1.11.1.min.js"></script>
    <script src="/Scripts/knockout-3.4.0.js"></script>
    <script src="/Scripts/globalize/globalize.js"></script>
    <script src="/Scripts/dx.webappjs.js"></script>
</head>

You will need to write JavaScript code for the view. Thus, first add a JavaScript file to your project and link it within the view.

HTML
<head runat="server">
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <link rel="stylesheet" type="text/css" href="/Content/dx.common.css" />
    <link rel="stylesheet" type="text/css" href="/Content/dx.light.css" />
    <script src="/Scripts/jquery-1.11.1.min.js"></script>
    <script src="/Scripts/knockout-3.4.0.js"></script>
    <script src="/Scripts/globalize/globalize.js"></script>
    <script src="/Scripts/dx.webappjs.js"></script>
    <script src="/MyJS/script_Knockout.js"></script>
</head>

Add a Button Widget

To create a button widget, add a div element with dxButton Knockout binding to the body of the HTML document, as shown in the code below.

HTML
<html>
    <!--...-->
    <body>
      <div data-bind="dxButton: { text: 'Generate random value' }"></div>
    </body>
</html>

As you can see in this code, a configuration object must be passed to specify configuration options for the widget. Here, the configuration object contains only the text option, which specifies the button text.

Since the browser doesn't know what the data-bind attribute means, you need to activate Knockout to make it take effect. To activate Knockout, call the ko.applyBindings() method once the page has been loaded.

JavaScript
window.onload = function () {
    ko.applyBindings();
};

The Knockout approach is based on the MVVM (Model-View-ViewModel) pattern. According to this pattern, your HTML Index view will be a View in terms of MVVM. This View will be linked to the ViewModel by declarative bindings. To create a ViewModel, just declare a JavaScript object within the JavaScript file you added previously. To indicate that this ViewModel object must be used with the declarative bindings that Knockout activates, pass the declared viewModel object to the applyBindings method as a parameter.

JavaScript
var viewModel = { };
window.onload = function () {
    ko.applyBindings(viewModel);
};

Handle Click Event

To handle a button click, assign a handling function to the onClick option of the widget.

Add a clickHandler field to the ViewModel object and bind the button's onClick configuration option to this field. Assign the required handling function to the clickHandler ViewModel field. In the code below, the handling function generates a string consisting of ten random digits and assigns it to the randomValue ViewModel field. To display the generated string on the screen, a <p> element is added and bound to the randomValue ViewModel field.

HTML
<body>
    <div data-bind="dxButton: {
            text: 'Generate random value',
            onClick: clickHandler
        }"></div>
    <p>Random value: <b data-bind="text: randomValue"></b></p>
</body>
JavaScript
var viewModel = {
    randomValue: ko.observable("0000000000"),
    clickHandler: function () {
        var result = "";
        for (var i = 0; i < 10; i++)
            result += Math.round(Math.random() * 9);
        this.randomValue(result);
    }
};
window.onload = function () {
    ko.applyBindings(viewModel);
};

Modify Option Value at Runtime

To change the enabled state of the button, add the dxCheckBox widget. When changing the check box value, the button will be enabled/disabled at runtime.

Add the dxCheckBox widget in the same manner as you added the dxButton widget. To change the button's enabled state when the check box value is changed, add an observable field to the ViewModel object. Bind the check box's value configuration option to this field. In addition, bind the button's disabled configuration option to this field. In this instance, when the check box's value is changed at runtime, the button's enabled state will be changed in response.

HTML
<body>
    <div data-bind="dxButton: {
        text: 'Generate random value',
        onClick: clickHandler,
        disabled: buttonDisabled
    }"></div>
    <p>Random value: <b data-bind="text: randomValue"></b></p>
    <p>Disable button <span data-bind="dxCheckBox: { value: buttonDisabled }"></span></p>
</body>
JavaScript
var viewModel = {
    randomValue: ko.observable("0000000000"),
    clickHandler: function () {
        var result = "";
        for (var i = 0; i < 10; i++)
            result += Math.round(Math.random() * 9);
        this.randomValue(result);
    },
    buttonDisabled: ko.observable(false)
};
window.onload = function () {
    ko.applyBindings(viewModel);
}

Angular Approach

To use an AngularJS approach, add the angular.js and angular-sanitize.js script libraries to the Scripts folder of your project. You can find these libraries in your DevExtreme package.

Reference the AngularJS libraries in the Index view.

HTML
<head runat="server">
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <link rel="stylesheet" type="text/css" href="/Content/dx.common.css" />
    <link rel="stylesheet" type="text/css" href="/Content/dx.light.css" />
    <script src="/Scripts/jquery-1.11.1.min.js"></script>
    <script src="/Scripts/angular.js"></script>
    <script src="/Scripts/angular-sanitize.js"></script>  
    <script src="/Scripts/globalize/globalize.js"></script>
    <script src="/Scripts/dx.webappjs.js"></script>
</head>

Add the ng-app directive to the html element of the document to specify the root element of the AngularJS application. Pass the application name as a directive parameter. Create the script_Angular.js file, which will contain scripts that you will create, and add the corresponding reference to the view's markup.

HTML
<html ng-app="myApp">
    <head runat="server">
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
        <link rel="stylesheet" type="text/css" href="/Content/dx.common.css" />
        <link rel="stylesheet" type="text/css" href="/Content/dx.light.css" />
        <script src="/Scripts/jquery-1.11.1.min.js"></script>
        <script src="/Scripts/angular.js"></script>
        <script src="/Scripts/angular-sanitize.js"></script>
        <script src="/Scripts/globalize/globalize.js"></script>
        <script src="/Scripts/dx.webappjs.js"></script>
        <script src="/MyJS/script_Angular.js"></script>
    </head>
    <body>
    </body>
</html>

Specify the module to load when bootstrapping the application and include the DevExtreme "dx" module in the list of dependencies for the application.

JavaScript
var myApp = angular.module('myApp', ['dx']);

Add a Button Widget

To add a button widget, add a div element with the dx-button AngularJS directive. The directive parameter specifies the widget configuration object. In the code below, the configuration object only contains the text option, which specifies the button text.

HTML
<body>
  <div dx-button="{
          text: 'Generate random value'
      }"></div>
</body>

Handle Click Event

To handle a button click, assign a handling function to the onClick option of the widget.

The event handling function should be declared within a controller associated with the current view. Call the controller() function of the myApp variable to create a controller. The first argument passed to this function specifies the controller name. The second argument specifies the controller constructor function.

JavaScript
var myApp = angular.module('myApp', ['dx']);
myApp.controller("defaultCtrl", function ($scope) {});

Add the ng-controller directive to the body element of the view to associate the controller with the view.

HTML
<body ng-controller="defaultCtrl">
    <div dx-button="{
            text: 'Generate random value'
        }"></div>
</body>

Now, the HTML elements within the body element can be associated with the fields of the $scope object that is provided by the controller constructor parameter. So, assign the click handling function to the clickHandler field of the $scope object and associate the onClick option of the widget with this field. In the code below, the handling function generates a string consisting of ten random digits and assigns it to the randomValue field of the $scope object. To display the generated string on the screen, a <p> element is added and bound to the randomValue scope field.

HTML
<body ng-controller="defaultCtrl">
    <div dx-button="{
            text: 'Generate random value',
            onClick: clickHandler
        }"></div>
    <p>
      Random value: <b>{{randomValue}}</b>
    </p>
</body>
JavaScript
var myApp = angular.module('myApp', ['dx']);
myApp.controller("defaultCtrl", function ($scope) {
    $scope.randomValue = "0000000000";
    $scope.clickHandler = function () {
        var result = "";
        for (var i = 0; i < 10; i++)
            result += Math.round(Math.random() * 9);
        $scope.randomValue = result;
    }
});

Modify Option Value at Runtime

To change the enabled state of the button, add the dxCheckBox widget. When changing the check box value, the button will be enabled/disabled at runtime.

To update the option value at runtime, provide two-way binding between the option and the corresponding field of the $scope object. For this purpose, add the bindingOptions field to the widget configuration object. This field contains options requiring two-way binding. Note that in this case, you should pass the name of the corresponding $scope object field instead of the field itself to the required option. Specify the disabled option value as it is demonstrated below and add the buttonDisabled field to the $scope object in the controller constructor function.

HTML
<body ng-controller="defaultCtrl">
    <div dx-button="{
      text: 'Generate random value',
      onClick: clickHandler,
      bindingOptions: { 
          disabled: 'buttonDisabled'
      }
    }"></div>
    <p>Random value: <b>{{randomValue}}</b></p>
    <p>Disable button <span dx-check-box="{ bindingOptions: { value: 'buttonDisabled' } }"></span></p>
</body>
JavaScript
myApp.controller("defaultCtrl", function ($scope) {
    //...
    $scope.buttonDisabled = false;
});       

Add the dxCheckBox widget to control the value of the buttonDisabled field. Provide two-way binding between the check box value option and the buttonDisabled scope field. Now, if you check or uncheck the check box, it updates the buttonDisabled field value, which updates the value of the button's disabled option appropriately.

HTML
<body ng-controller="defaultCtrl">
    <div dx-button="{
        text: 'Generate random value',
        onClick: clickHandler,
        bindingOptions: { 
            disabled: 'buttonDisabled'
        }
    }"></div>
    <p>Random value: <b>{{randomValue}}</b></p>
    <p>Disable button <span dx-check-box="{ bindingOptions: { value: 'buttonDisabled' } }"></span></p>
</body>