Your First Mobile App in Visual Studio

This tutorial will walk you through creating your first DevExtreme application. It will be a basic HTML JS single-page application. Along the way, you will define two views by creating HTML templates and ViewModels. In addition, you will add simple actions to move between these views.

Download Code Watch Video

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, 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 within the Solution Explorer. It includes the following.

    New Project Dialog

  • css - A folder with common and platform-specific stylesheet files.

  • data - A folder intended for everything that is related to data, e.g., objects to which data is loaded.
  • 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 two sample views - "home" and "about". 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 as home.html and implement an 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 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 the 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 are added.
  • index.css - A file with application stylesheets.
  • 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 configuration inludes a navigation type. It is a strategy according to which a certain page layout is applied in the current context. In the project template, the "navbar" type 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). 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.

  • Run the application in any browser to test the application template. The application will be shown by the simulator - one of the tools that come with the DevExtreme VS extension. The simulator allows you to see 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 result in a simulator.

Try a custom markup

  • Remove the default view content, leaving the div element that has the data-options attribute set to dxView and the div element that has the data-options attribute set to dxContent. The first one defines a view template, 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' } " >
            Welcome!
        </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 there. 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's 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 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 clickAction 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', clickAction: 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 PhoneJS 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.

    Categories List View

  • Within the invoked dialog, choose the View template, specify "greeting" as the name 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 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 a view in the Add New Item dialog is used to name the fake function in the JavaScript file, check that the name configuration option of the view's markup has the same name. Alternatively, you can change the function's name, but keep it 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",
          "action": "#home",
          "icon": "home"
        },
        {
          "title": "About",
          "action": "#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 confirms 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 clickAction 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', clickAction: sayHello }"></div>
        <div data-bind="dxButton: { text: 'Greet', clickAction: 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 if the implemented navigation operates correctly. 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 the 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 name field value (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;
};