I would like to use some JavaScript controls, which have KnockoutJS binding handlers already implemented. After reviewing the DotVVM tutorials, such as "Code-only Controls" and also the controls from the DotVVM source code, I am confused on what aspects of and to what extent the controls need to be rendered via the DotVVM "Rendering Pipeline," if indeed they need to be.

Also, if the controls already have KnockoutJS binding handlers already implemented, is the process of wrapping them the same as for controls which do not have KnockoutJS binding handlers already implemented?

1

There are 1 best solutions below

1
On BEST ANSWER

If you already have Knockout binding handlers, you just need to write a control to render the appropriate HTML.

The only difficulty here is that the values of control properties may be hard-coded in the markup, or it can be a data-binding. Some properties allow only one of these ways, some allow both.

Basically, you need to create a class inherited from HtmlGenericControl and tell it which HTML element it should render, in the base constructor. For example: public MyControl() : base("div").

Then you need to declare control properties. Use the dotprop code snippet to generate the property body, and using the MarkupOptions attribute you can disable hard-coded values or data-bindings if it doesn't make sense.

And finally, you need to render the HTML. If you need to render only the data-bind attribute, you need to override just the AddAttributesToRender.

You can call writer.AddKnockoutDataBind("myBindingHandler", this, MyProperty, () => { /* handle the hard-coded value */ } ). If the property contains a data-binding, it will get translated automatically. If it contains a hard-coded value, the last argument (the lambda) will be called.

If the control is more complex and uses templates or invokes postbacks, you need to build child controls inside the control, set their bindings properly and you don't need to render them manually in that case.

There are several reasons why DotVVM uses such a complex rendering pipeline:

  • Since the properties can contain both data-bindings and hard-coded values, you would end with many if statements. Sometimes, the binding is evaluated on the server, sometimes it is translated to JS. Moreover, some controls are very complex and need to build some child controls.
  • Knockout needs all properties declared in the data-bind attribute. They are separated by a comma, so the API handles the concatenation and translation to proper JavaScript expressions.
  • Splitting the control rendering into the AddAttributesToRender, RenderBeginTag, RenderContents and RenderEndTag methods allows to extend the controls using inheritance. We have copied this from ASP.NET Web Forms because it worked quite well.

If you can provide an example of what are you trying to render, I can give more specific answer.