Client-side development overview

Most of the time, you will be spending your time writing a server-side code in C# viewmodels. Thanks to the MVVM experience, it is possible to implement interactive pages with client-side without writing any JavaScript code.

However, in order to create more advanced experiences for the users, or if you want to integrate third-party libraries or components into DotVVM pages, you will need to work with the client-side part of DotVVM.

Value binding and static commands

Even without digging into JavaScript, there is a way to invoke actions in the browser without the need to communicate with the server - the static commands. They can be used to perform simple client-side manipulations to the viewmodel:

<dot:Button Text="Show modal" 
            Click="{staticCommand: MyModalDialog.IsDisplayed = true}" />

Also, thanks to the translation of value binding and MVVM, you can use complex expressions to manipulate with the user interface components:

<!-- This button will be visible only when at least one category is selected -->
<dot:Button Text="Delete selected categories"
            Visible="{value: SelectedCategories.Count > 0}" 
            Click="..." />

<!-- Checkboxes which are checked, put theirs CheckedValue into the SelectedCategories collection -->
<dot:Repeater DataSource="{value: AllCategories}">
    <dot:CheckBox Text="{value: CategoryName}" 
                  CheckedValue="{value: Id}"
                  CheckedItems="{value: _parent.SelectedCategories}" />

DotVVM JavaScript API

If you need to do something serious on the client, e. g. integrate a third-party JavaScript component in the page, DotVVM offers a public client-side API that can be used to access the viewmodel, or subscribe to various DotVVM events.

The following code snippet shows how to read a value from the viewmodel, and run JavaScript code after the DotVVM is initialized:

// run code after DotVVM is initialized () {
    var map = new google.maps.Map(document.getElementById('map'),
        center: {
            lat: dotvvm.state.Latitude,  // read a value from the viewmodel
            lng: dotvvm.state.Longitude
        zoom: 8

JS directive

The previous approach is great for simple, one-time interactions. If you need something more sophisticated, you can organize your JavaScript code as an ES module, and allow two-way interaction with DotVVM code.

You can register a module in the page using the @js directive:

@js MapsModule

The module looks like this:

export default context => new Page(context);
class Page {
    constructor(context) { = new google.maps.Map(...);"zoom_changed", () => {
            // you can call a NamedCommand in DotVVM page

    // you can expose functions which can be called from DotVVM using _js.Invoke
    setPosition(latitude, longitude) {{ lat: latitude, lng: longitude });

The module exposes an object which can:

  • call commands defined using the NamedCommand control in the DotVVM page
  • be called from static commands using _js.Invoke("functionName", args...)
<!-- This can be called from the JS module using 
     context.namedCommands["ZoomChanged"](args...) -->
<dot:NamedCommand Name="ZoomChanged" 
                  Command="{staticCommand: (int zoom) => ...}" />

<!-- You can call functions in the module from static commands-->
<dot:Button Text="Set position"
            Click="{staticCommand: _js.Invoke("setPosition", Latitude, Longitude)"} />

See the JS directive chapter for more info.

Other options

There are even more advanced options which may be helpful when developing custom controls or extending DotVVM. See the Control development section for more info.

See also