Background
The HtmlReport functionality takes an XHTML string and processes it, adding data from a ViewModel and outputting the resulting XHTML.
XHTML is a strict version of HTML that is XML-compatible. More importantly, it always has one, and only one, root node. Read more here: https://en.wikipedia.org/wiki/XHTML
All the functionality of the HtmlReport functionality also applies to XML if you need that.
The HTML-generating functions share most of their code with the OpenDocument functionality. The OpenDocument format uses XML for storing the document content.
Usage
- ViewModel that defines data to insert
- Template to insert data into
Create a ViewModel that extracts the data you need from your model. Each attribute in this ViewModel can replace one or more "tags" in the source template. Note that the ViewModel also defines where the template can be found.
Example of a ViewModel that extracts two attributes to be used, "String" and "Text":
Ways to Retrieve the Template
The template is accessed in several different ways:
- From a String attribute in a modeled class
- From a BLOB attribute in a modeled class (base64 encoded)
- From a URL
- From the local filesystem
Attribute name | Attribute should evaluate to | Value type and content |
TemplateHtml | A string that contains Html | Not encoded in any special way |
TemplateUrl | The URL or local filename | String with for example http://www.mdriven.net/templates/report.odt or for prototyping c:\\temp\\mytemplate.odt |
TemplateBlob | A class attribute containing the template | Blob with an uploaded document template, value is expected to be Base64 encoded |
ReportFileName | A string with a filename | Not used by XHtmlReportAsString but needed for opendocumentreportasblob |
Methods
Depending on your input format, you can use either of these two functions:
XHtmlReportAsString
Easiest to use - takes the string input and returns another string. No encoding of the input HTML is required.
ResultHtmlAsString := self.XHtmlReportAsString(ReportRoot.ViewModels.ReportingViewmodel)
opendocumentreportasblob
Takes an array of bytes as input and output. The content should be UTF-8 encoded and in Base64 format.
To encode a Blob as base64, use BlobToBase64. (This will return a string base64 encoded, that will, in turn, be used as Blob.)
To encode a String as base64, use StringToBase64. (This will return a string base64 encoded, that will, in turn, be used as Blob. )
ResultHtmlAsBlob := self.opendocumentreportasblob(ReportRoot.ViewModels.ReportingViewmodel)
opendocumentreportshow
Does the same as opendocumentreportasblob above, but opens the resulting HTML in the browser.
self.opendocumentreportshow(ReportRoot.ViewModels.ReportingViewmodel)
Inputs
- self here will become the root object of the reporting ViewModel.
- ReportRoot is the class that has the reporting ViewModel.
- Viewmodels is a method that retrieves all the ViewModels of the class. See ViewModels.
- ReportingViewmodel is the name of the reporting ViewModel used in this example.
Tags
Tags are the attribute name surrounded by percentage signs %. See %Date% and %Customername% below.
Multi-links form lists in the ViewModel. The name of the multi-link, in the example below, Invoices will repeat the HTML tag it's contained in, along with its content. The repeat tag is %%+ at the start and ends with %. Invoices will become %%+Invoices%. In the example below, this will repeat the <tr> tag with its containing Date and Customer name forming a list in HTML.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <body> <table> <tbody> <tr> <td>Date</td> <td>Customer</td> </tr> <tr>%%+Invoices% <td>%Date%</td> <td>%Customername%</td> </tr> </tbody> </table> </body> </html>
Tips & Tricks
Having a Collection of Strings
If you have a collection of strings (or create a collection of strings from a comma list, for example) that you want to be rendered as a list of rows (paragraphs for example), let the ViewModel column return the expression return a collection of strings, then create a new ViewModel class (blue) without setting its type (derived from ViewModel), then add a column inside that ViewModel that has "self" as its expression.
In your HTML, you can then use:
<p>%%+Viewmodel.AttributeOfCollection% %NameOfValueAttribute%</p>
Now the transformation will iterate the collection Viewmodel.AttributeOfCollection and fill in the value in NameOfValueAttribute
XHtml
Because an Html document might be unloadable into a DOM tree like XHtml or XML, you should try providing a single document root node.
Providing plain HTML might be easier, and several HTML editors usually don't output Xhtml. Because of this, XHtmlReportAsString will try to compensate and add a <html> tag around the content if it's missing. For example, this input, which has no single root node, has only two <p> tags
<p>Hello %String%</p> <p>You need to do this....</p>
It will create this output:
<html> <p>Hello John</p> <p>You need to do this....</p> </html>
The <html> tag was added because there were no <root>, <body>, or <html> tags in the input document.
Information About Available Tags (Meta Data)
When creating template documents, consider using the value %meta% in your document to get the exact tag list for your document.
In Html, provide a tag to hold the meta value, like this:
<meta>%meta%</meta>
Will create a ViewModel, for example:
<html> <meta>%TemplateHtml%, %TemplateBlob%, %ReportFileName%, %String%, %Text%, </meta> </html>
Copy the tag name including the percent signs from the generated meta tag information. The %meta% must be the first string in the element in order to be recognized.
XML Documents
XML is the more generic case of HTML. They are treated by the same logic.
<SomeXml attrib='%SomeVMColumnAsAttributeresult%'> %SomeOtherVMColumnAsXMLTextresult% <Items> <Item>%%+TheVMNestingColumn% <ContentInItem someattrib='%VMColInNesting%'> %StuffFromViewModelNesting% </ContentInItem> </Item> </Items> </SomeXml>