Your First Mobile App in Visual Studio

This tutorial will walk you through creating your first DevExtreme application in Visual Studio. It will be a basic HTML JS single-page application built using the DevExtreme SPA Framework and DevExtreme UI widgets. Along the way, you will define two views by creating HTML templates and ViewModels. In addition, you will implement navigation between these views.

See Also
  • If you are not going to use Visual Studio to develop DevExtreme mobile application, follow the Your First Application tutorial. It is similar to this one and allows you to get started with the DevExtreme SPA framework.
  • You can find more tutorials on using the DevExtreme SPA framework in the SPA Framework Tutorials section.
  • Follow the tutorials located in the VS Integration Tutorials section to learn more about specifics of developing DevExtreme mobile applications in Visual Studio.

Watch Video

Download Code

Create an Application Project

  • From the main menu in Visual Studio, select File | New | Project... to invoke the New Project dialog.

    New Project Dialog

  • In the Projects tree view on the left, select DevExtreme. In the Templates list view, select the DevExtreme XX.X Basic Application template, specify the new solution's name ("Application1" in this example) and click OK. You will see a project with the specified name in the Solution Explorer. It includes the following.

    Solution Structure

    • css
      A folder with common and platform-specific style sheet files.
    • js
      A folder with all the JavaScript libraries required for the application.
    • layouts
      A folder with the files representing the predefined layouts that come with the framework.
    • views
      A folder with three sample views - "home", "about" and "blank". The "home" view is implemented in three files:

      • home.dxview
        An HTML template for the "home" view. Since this file has the .dxview extension, a View Designer is used to open this file. You can rename this file to home.html and implement HTML markup for the view without using the View Designer, although the View Designer is helpful.
      • home.css
        A set of CSS rules applied to the view's markup.
      • home.js
        The working JavaScript code for the view.

      The view's HTML template, together with the applied CSS classes, is a View in terms of the MVVM pattern. According to this pattern, Views can be bound to corresponding ViewModels. The ViewModel is basically your custom JavaScript code, which is responsible for providing data from the Model to the View taking into account different user interactions. The Model is represented by the data that you can obtain from virtually anywhere. So, you may choose to connect to remote data sources via AJAX requests, bind to JavaScript objects or even use HTML5 local storage.

      The "about" view is rather simple and presented by a single about.html file.

    • index.html
      An application page where all the required resources are linked and a div element working as a view port is added.

    • index.css
      A file with application style sheets.
    • index.js
      A file where the HtmlApplication object is created and configured.
    • app.config.js
      A file that includes the configuration object used to initialize the application. The following configuration options are predefined in this file.
      • layout set.
        In the project template, the "navbar" layout set is specified. This means that the Navbar layout will be used in major views (make sure that it is linked in the index.html file).
      • navigation
        To configure the dxNavBar widget used in the "navbar" layout as a navigation control, the navigation option is specified for the application. The array assigned to this option specifies configuration options for navigation items. As you can see, the "home" and "about" views will be available from the navigation control.
      • animationSet
        Specify the 'default' animation set for the application. This is a predefined animation set. The animations it includes are used by the "navbar" layout to animate transitions between views. In addition, animations from this set can be used for list and detail views to make them 'live' and attractive. For details, refer to the Animation guide.
  • Run the application in any browser to test the application template. The application will be shown by the simulator - one of the tools included with the DevExtreme VS extension. The simulator allows you to view an application on different devices using the required landscape and scale.

Run in Simulator

As you can see, the views that are added by default are loaded to the application and you can navigate between them using a navbar. The "navbar" layout is designed for each platform individually. So, when you switch between devices, the appropriate layout version and style sheets are applied, and the application looks native.

Modify the Home View

Open the home.dxview file. In the View Designer, you can write HTML code and see the results in a simulator.

Add Custom Markup

  • Remove the default view content, leaving the div element with the data-options attribute set to dxView and the div element with the data-options attribute set to dxContent. The first one defines a view template and the second one indicates the placeholder to which the view content must be inserted in the layout applied to the view.

    HTML
    <div data-options="dxView : { name: 'home', title: 'Home' } " >
        <div class="home-view" data-options="dxContent : { targetPlaceholder: 'content' } " >    
        </div>
    </div>

    Note that the name given to the view using the name configuration option of the dxView component is important. The specified name will be used to identify the view.

  • Add the h1 element and write "Welcome" in it.

    HTML
    <div data-options="dxView : { name: 'home', title: 'Home' } " >
        <div class="home-view" data-options="dxContent : { targetPlaceholder: 'content' } " >
            <h1>Welcome!</h1>
        </div>
    </div> 
  • Click the simulator to update its content. The new view content will be displayed in the simulator.

    Home View in the Designer

Bind the View to the ViewModel

Open the home.js file. A JavaScript function has already been implemented. This function is associated with the "home" view because it has the same name as the view's HTML template. The object returned by this function is a ViewModel object. Do the following to bind a view element to the ViewModel field.

  • Add the message field to the ViewModel object. Set this field to "Welcome!"

    JavaScript
    Application1.home = function () {
        var viewModel = {
            message: 'Welcome!'
        };
        return viewModel;
    };
  • In the view's HTML template, replace the simple "Welcome!" string with the h1 element bound to the message field of the ViewModel via the text Knockout binding.

    HTML
    <div data-options="dxView : { name: 'home', title: 'Home'} " >
        <div class="home-view" data-options="dxContent : { targetPlaceholder: 'content' } " >
            <h1 data-bind="text: message"></h1>
        </div>
    </div>
  • Run the application to check that the message field value is displayed on the "home" view.

Update a ViewModel Field Dynamically

Do the following to add a text box to the "home" view and concatenate the "Welcome!" text with the entered text at runtime.

  • In the home.js file, make the ViewModel's message field observable.
  • In the home.js file, add an observable name field to the ViewModel.

  • Open the home.dxview file in the View Designer. In the DevExpress Mobile Widgets section of the Toolbox, find the dxTextBox widget and drag and drop it to the simulator. Bind the text box's value configuration option to the name field of the ViewModel.

  • Add the dxButton widget to the view in the same way you added the dxTextBox widget. Assign the sayHello ViewModel field to the onClick configuration option of the button. In the home.js file, add the sayHello field to the ViewModel and assign a function to it. In this function, update the value of the ViewModel's message field when the name field is changed.

HTML
<div data-options="dxView: {name: 'home', title: 'Home'}">
    <div class="home-view" data-options="dxContent : { targetPlaceholder: 'content' } " >
        <h1 data-bind="text: message"></h1>
        Enter your name: <div data-bind="dxTextBox: { value: name }" style="width: 200px"></div>
        <div data-bind="dxButton: { text: 'Say Hello', onClick: sayHello }"></div>
    </div>
</div>
JavaScript
Application1.home = function () {
    var viewModel = {
        message: ko.observable('Welcome!'),
        name: ko.observable(''),
        sayHello: function () {
            this.message("Hello " + this.name() + '!');
        }
    };
    return viewModel;
};

As you can see in the code above, we used the dxTextBox and dxButton widgets from the DevExtreme widget library. These widgets are supplied with styles for each platform so that your application looks native on any platform. These styles are collected in platform-specific CSS files that are already linked in the index.html file.

Add a New View

Add a new view to the views folder.

  • Right-click the views folder in the Solution Explorer and choose Add | New Item... in the context menu, which will invoke the Add New Item dialog.

    Greeting View

  • In the invoked dialog, choose the View template, specify the name as "greeting" and click Add. As a result, you will get automatically generated greeting.dxview and greeting.js code files. These files will be registered within the index.html file automatically.

  • Remove the default content from the greeting view's HTML template and add the h1 element bound to the message field of the ViewModel.

Here is the code that you will get.

HTML
<div data-options="dxView : { name: 'greeting', title: 'greeting' } " >
    <div class="home-view" data-options="dxContent : { targetPlaceholder: 'content' } " >
        <h1 data-bind="text: message"></h1>
    </div>
</div>
JavaScript
Application1.greeting = function (params) {
    var viewModel = {
        message: 'Hello!'
    };
    return viewModel;
};
NOTE
The function implemented in the newly added JavaScript file must have the same name as the value of the name configuration option of the view's markup. Since the name given to the view in the Add New Item dialog is used to name the fake function in the JavaScript file, check to make sure that the name configuration option of the view's markup has the same name. Alternatively, you can change the function's name, but make sure it is similar to the view's name in the markup.

Run the application. The newly added view is automatically added to the application's navigation.

Add Navigation between Views

By default, the "greeting" view is added as a root view (available from the navigation control). Do the following to treat this view as a secondary view, and navigate to it using a button on the "home" view.

  • In the app.config.js file, remove the object that represents the "greeting" navigation item from the array that is assigned to the navigation option of the HtmlApplication's configuration object.

    JavaScript
    "navigation": [
        {
          "title": "Home",
          "onExecute": "#home",
          "icon": "home"
        },
        {
          "title": "About",
          "onExecute": "#about",
          "icon": "info"
        }
    ]
  • Add the greet function to the "home" view's ViewModel. In this function, call the navigate method of the HtmlApplication object, passing "greeting" as a parameter. "greeting" is the name of the view to which to navigate. This parameter value conforms to the routing format that is specified for the application by default (see the index.js file).

  • Add the dxButton widget to the "home" view's HTML template and bind its onClick option to the ViewModel's greet function.
HTML
<div data-options="dxView: {name: 'home', title: 'Home'}">
    <div class="home-view" data-options="dxContent : { targetPlaceholder: 'content' } " >
        <h1 data-bind="text: message"></h1>
        Enter your name: <div data-bind="dxTextBox: { value: name }" style="width: 200px"></div>
        <div data-bind="dxButton: { text: 'Say Hello', onClick: sayHello }"></div>
        <div data-bind="dxButton: { text: 'Greet', onClick: greet }"></div>
    </div>
</div>
JavaScript
Application1.home = function () {
      var viewModel = {
          message: ko.observable('Welcome!'),
          name: ko.observable(''),
          sayHello: function () {
              this.message("Hello " + this.name() + '!');
          },
          greet: function () {
              Application1.app.navigate("greeting");
          }
      };
      return viewModel;
  };

Run the application to see that the implemented navigation operates properly. Note that the "navbar" layout automatically adds a Back button to the "greeting" view. For details on navigation, refer to the Navigation and Routing article.

Pass a Parameter to a View

Pass the text entered in the "home" view to the "greeting" view and concatenate it to the "Hello" string.

  • In the index.js file, check to make sure that the application's routing format allows you to pass a parameter. By default, the routing format has a second id parameter.

    JavaScript
    Application1.app.router.register(":view/:id", { view: "home", id: undefined });
  • In the "home" ViewModel's greet function, expand the parameter passed in the navigate function with the value of the name field (the value entered in the text box). This will conform to the new routing format.

  • Make the message field of the "greeting" ViewModel observable. Set this field to the text passed as a parameter from the view's URL.
JavaScript
greet: function () {
    Application1.app.navigate("greeting/" + this.name());
}
JavaScript
Application1.greeting = function (params) {
    var viewModel = {
        message: ko.observable('Hello ' + params.id + '!')
    };
    return viewModel;
};