Custom JavaScript translators

DotVVM implements an extensible binding translations mechanism, which is an API for building abstract syntax trees (AST) that represent JavaScript expressions. We can then register custom translators for specific .NET methods, and extend the set of supported methods used in data bindings.

Register custom translator

Every translator must implement the IJavascriptMethodTranslator interface. However, it is a bit simpler to utilize a general-purpose implementation called GenericMethodCompiler exposed by DotVVM.

Example 1: translator for Enumerable.Where method

In the following code snippet, we will create a custom translation for the method Where(source, predicate) on the type System.Linq.Enumerable. Whenever constructing the GenericMethodCompiler, we need to provide a transformation for the provided method arguments. In this case, we need to work with two arguments: 1) source collection, 2) predicate that filters elements. Therefore, an example translator that combines these arguments into a JavaScript expression can be seen in the code snippet below:

var translator = new GenericMethodCompiler(args => args[1].Member("filter").Invoke(args[2]));

In the code snippet above, args[1] represents the source collection, and args[2] represents the predicate. When used, this translator will yield the following JavaScript expression: args[1].filter(args[2]).

At this point, you might notice that we are indexing the args array from 1. Actually, the zero-th array element represents the this pointer. Since in C# the Where method is static, the zero-th array element is null, and as such is not used by the translator. The only step left is to register the new translator. This can be achieved in DotvvmStartup.cs file using the following code snippet.

var whereMethodInfo = /* obtain method info using reflection */;
config.Markup.JavascriptTranslator.MethodCollection.AddMethodTranslator(whereMethodInfo, translator);

Example 2: Translator for Array.Length property getter method

In the following code snippet, we will create a custom translation for the Length property getter method on the type System.Array. In this case, we need to work with a single arguments that represents the array. Since the Length property is bound to a specific instance, the array argument is passed as the this pointer, which corresponds to the args[0] expression. An example translation can be seen in the code snippet below.

var translator = new GenericMethodCompiler(a => a[0].Member("length"));

When used, the translator above will yield the following JavaScript expression: args[0].length. Now, the only thing left is registering this translation. We can perform the registration using the following code snippet.

AddPropertyGetterTranslator(typeof(Array), nameof(Array.Length), translator);

See also