BorisMoore / jsviews

Interactive data-driven views, MVVM and MVP, built on top of JsRender templates
http://www.jsviews.com/#jsviews
MIT License
856 stars 130 forks source link

Generate template from JSON Schema #383

Closed mcartmel closed 7 years ago

mcartmel commented 7 years ago

I have a series of JSON Schema's that change regularly (they are generated by another system) and I'm currently trying to figure out the best way to convert these on-the-fly to JSViews templates. I would prefer to do it in the browser rather than compile them server side, as I'm trying to keep the server as lightweight as possible.

Any advice on how I can achieve this?

BorisMoore commented 7 years ago

Thanks Michael. You can use JsRender itself to generate your JsRender/JsViews templates from the JSON Schema. You can create a template (to generate a template) with different delimiters.

http://www.jsviews.com/#settings/delimiters@tmpl-for-tmpl

I'll add more details here soon...

mcartmel commented 7 years ago

Thanks Boris! It hadn't occurred to me to use this function. I'm looking into it now.

BorisMoore commented 7 years ago

Basically the idea is as follows:

You have data instances conforming to a JSON Schema, and you want to have one or more templates for your UI, running against that data. When the JSON Schema changes, you want to be able to modify your templates so that they continue to run correctly against the new data - instances of the new JSON Schema.

So for each template you need for your UI, you will create a 'baseTmpl' template, which uses as data the JSON Schema itself. You use the baseTmpl template (or templates) to generate the actual templates you will use, which will run against the instance data of the Schema.

There is a sample here: https://jsfiddle.net/BorisMoore/y6qtp6z5/.

In order for your master template, 'baseTmpl', to be able to generate a template which will include JsRender tags, such as {{:foo}} or {^{for ...}} ... you need to make it use different delimiters (such as <% ... %> - so there is no clash or conflict between 'generating markup' and 'output markup'.

So your master template will include things like this:

<%for properties.style%>
  ...
  <label for="field_arg.style{{:#getIndex()}}">Style</label>
  ...
<%/for%>

And the code will be along the lines of:

var schema = schema2;
var data = data2

// Temporarily switch delimiters
$.views.settings.delimiters("<%", "%>");

var generatedTemplate = $.templates("#baseTmpl").render(schema);

// Revert to original delimiters
$.views.settings.delimiters("{{", "}}");

// Render data using generated template
var tmpl = $.templates(generatedTemplate);

tmpl.link("#result", data, {
  ...
});
mcartmel commented 7 years ago

Thanks again Boris.

I've created a fiddle which demonstrates this technique and renders a JSON Schema as a Bootstrap styled form. I'm in the process of adding an array handler to this as well.

BorisMoore commented 7 years ago

I'm closing this issue, as resolved...