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.
If you plan to use TypeScript, check out the TypeScript declarations chapter on how to obtain the definition files and get IntelliSense and type checking for interactions with DotVVM client-side API.
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}" />
</dot:Repeater>
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
dotvvm.events.initCompleted.subscribe(function () {
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) {
this.map = new google.maps.Map(...);
this.map.addListener("zoom_changed", () => {
// you can call a NamedCommand in DotVVM page
context.namedCommands["ZoomChanged"](this.map.getZoom());
});
}
// you can expose functions which can be called from DotVVM using _js.Invoke
setPosition(latitude, longitude) {
this.map.setCenter({ 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.