Skip to content

Instantly share code, notes, and snippets.

@tomasherceg
Created July 6, 2020 09:16
Show Gist options
  • Save tomasherceg/eedd3fce82a28eaaadcb390f1ebdcf53 to your computer and use it in GitHub Desktop.
Save tomasherceg/eedd3fce82a28eaaadcb390f1ebdcf53 to your computer and use it in GitHub Desktop.
Proposal of DotVVM & JS modules usage
@viewModel DotvvmLovesJsSample.ViewModels.DefaultViewModel, DotvvmLovesJsSample
@jsModule Scripts/map
<h1>Map Demo</h1>
<div id="map"></div>
<form>
<div>Latitude: <dot:TextBox Text="{value: Lat} /></div>
<div>Longitude: <dot:TextBox Text="{value: Lng} /></div>
<div>
<dot:Button Text="Add Marker"
Click="{staticCommand: _js.Invoke("AddMarker", Lat, Lng)}" />
</div>
</form>
<dot:Repeater DataSource="{value: Events}" WrapperTagName="ul">
<li>{{value: _this}}</li>
</dot:Repeater>
<dot:NamedCommand Name="MarkerClicked"
Command="{command: (lat, lng) => OnMarkerClicked(lat, lng)}" />
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using DotVVM.Framework.ViewModel;
namespace DotvvmLovesJsSample.ViewModels
{
public class DefaultViewModel : DotvvmViewModelBase
{
public double Lat { get; set; }
public double Lng { get; set; }
public List<string> Events { get; set; } = new List<string>();
public void AddMarker(double lat, double lng)
{
Events.Add($"Clicked marker on {lat}:{lng}");
}
}
}
// this declaration will be a part of the DotVVM module
type DotvvmJsModuleContext = {
sender: HTMLElement;
state: any;
importedCommands: { [name: string]: (...args: any[]) => Promise<any>}
}
export var requiredNamedCommands = ["MarkerClicked"];
export function init(context: DotvvmJsModuleContext) {
let map = new google.maps.Map(context.sender.querySelector("#map"), {
center: { lat: -34.397, lng: 150.644 },
zoom: 8
});
map.addListener('center_changed', function(e) {
let pos = e.latLng;
// TODO: how to update the viewmodel from JS event handlers in init?
dotvvm.viewModels.root.viewModel["Lat"](pos.lat);
dotvvm.viewModels.root.viewModel["Lng"](pos.lng);
});
// TODO: we need to store map in context.state in order to work with it later
context.state.map = map;
}
export var jsCommands = {
// TODO: the specs suggested to pass arguments as an array, but I think it's more convenient to supply the arguments not as an array
// TODO: I've moved the sender in the context - not sure if this is OK
"AddMarker": function (context: DotvvmJsModuleContext, lat: number, lng: number) {
let marker = new google.maps.Marker({
position: { lat: lat, lng: lng },
map: context.state.map
});
marker.addListener('click', function() {
let pos = marker.getPosition();
// again, I tried to pass arguments not as an array but just as arguments - it seems more natural
context.importedCommands.MarkerClicked(pos.lat, pos.lng);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment