====================================== Dynamic content in your template - PD ====================================== A document template is just that, a template. You can add any source of information to be included. * As a discreet value * As an object with properties * An array or dictionary * As a template to use. * To make decisions on layout And they can be used in your document in many locations * Within the document content * On styles and classes * In templates and loops * Referenced content The notation for an binding on an attribute or content is based on the { and } with a method (@ for the built model), a colon ':', and then finally the selector. e.g. `attribute='{@:paramName}'` for values or `attribute='{@:paramName.property[index].value}'` for objects or even in textual content. Document parameters --------------------- Every Document can have parameters associated with it, and these can simply be bound to the content. This includes style and value properties as well as text, and can be set after parsing the content. .. code-block:: html {@:DocTitle}
{@:DocAuthor}

{@:DocTitle}

{@:DocContent}
And the value can be set or changed at runtime .. code-block:: csharp using (var doc = Document.ParseDocument(path)) { //pass paramters as needed, supporting simple values, arrays or complex classes. using (var stream = DocStreams.GetOutputStream("documentation.pdf")) { doc.Params["DocTitle"] = "Binding Title"; doc.Params["DocAuthor"] = "Binding Name"; doc.Params["ThemeHeader"] = "background-color:#EEE;padding:5pt"; doc.Params["DocContent"] = "This is the content of the document"; doc.SaveAsPDF(stream); } } And this will be used in the output. .. image:: images/documentbinding1.png Using objects -------------- Simple values work well, but with complex entries it will start to get extremely complex. Scryber supports the standard object notations for properties arrays and dictionaries to help divide up the binding. As a use case, we may need some purchase details. .. image:: images/documentbinding2.png .. code-block:: html {@:Content.Title}
{@:Content.Title}
{@:Content.Author}

{@:Content.Title}

Item Price Qty Total
Tax: {@:Model.Tax.Rate} {@:Model.Tax.Value}
{@:Model.Total.Value}
Kind regards
{@:Content.Author}
And with that we can bind the source into the document .. code-block:: xml using (var doc = Document.ParseDocument(path)) { //pass paramters as needed, supporting simple values, arrays or complex classes. using (var stream = DocStreams.GetOutputStream("documentation.pdf")) { doc.Params["Theme"] = new { Header = "background-color:#666; color: white;padding:5pt", Logo = "./images/ScyberLogo2_alpha_small.png" }; doc.Params["Content"] = new { Title = "Purchase List", Author = "The Scryber Team" }; doc.Params["Model"] = new { Items = new[] { new { Item = "First Item", Quantity = "4", Price = "€50.00", Value = "€200.00" }, new { Item = "Second Item", Quantity = "2", Price = "€25.00", Value = "€50.00" }, new { Item = "Third Item", Quantity = "3", Price = "€100.00", Value = "€300.00" } }, Tax = new { Rate = "20%", Value = "€110.00" }, Total = new { Value = "€660.00" } }; doc.SaveAsPDF(stream); } } Injecting content ------------------ If it is needed to inject some dynamic content within the document then it is easy to look up elements and then add the content either as html or as code. Let's say the ask was to add an optional foot note to our Purchase list for the high demand items, and also a custom footer to the pages. We can do this in our code, without changing the template. .. code-block:: csharp if (IsHighDemandItem()) { //Add the content to the footnote var div = doc.FindAComponentById("footnote") as Div; //Lets do this via conversion of dynamic xhtml into a component //Still needs to be valid XHTML var footnoteContent = "
Warmest regards from all the scryber team
" + "" + System.Environment.UserName + "

" + "Your order is for a high demand item. Please allow 6 weeks for delivery
"; var content = doc.ParseTemplate(doc, new System.IO.StringReader(footnoteContent)) as Component; //Remove the old content, as we want to div.Contents.Clear(); div.Contents.Add(content); } The string content is parsed, so needs to be xhtml, but then simply added to an existing div with a matching ID. And for the footer, we use the IPDFTemplate that is used for all dynamic content building - Headers, Footers, HTMLTemplates, etc. .. code-block:: csharp //Add the custom footer doc.Pages[0].Footer = new CustomFooter(); /// /// Implements the IPDFTemplate for a custom footer. /// public class CustomFooter : IPDFTemplate { /// /// Returns the object content (may be called multiple times). /// public IEnumerable Instantiate(int index, IPDFComponent owner) { //Wrap it all in a div so we can set the style Div div = new Div() { StyleClass = "footer", FontSize = 10, Padding = new PDFThickness(10), HorizontalAlignment = HorizontalAlignment.Center }; div.Contents.AddRange(new Component[] { new TextLiteral("Page Number "), new PageNumberLabel() { DisplayFormat = "{0} of {1}"} }); return new IPDFComponent[] { div }; } } As you can see, pretty much anything can be data bound and the output can be altered in any way using the combination of styles, declarative html content, data objects and code. As expected this will flow with the layout of the document and maybe even onto another page. .. image:: ./images/documentbinding3.png